diff --git a/src/tools/sysdb/main.c b/src/tools/sysdb/main.c
index 9b575cc825746c47548b87968090c65c0d77b6b2..357ef34827672d0033030eeefe8d85d059f98836 100644 (file)
--- a/src/tools/sysdb/main.c
+++ b/src/tools/sysdb/main.c
# 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 <errno.h>
# define DEFAULT_SOCKET "unix:"LOCALSTATEDIR"/run/sysdbd.sock"
#endif
-extern int yylex(void);
+static const char *
+get_homedir(const char *username)
+{
+ struct passwd pw_entry;
+ struct passwd *result = NULL;
+
+ /* needs to be static because we return a pointer into this buffer
+ * to the caller */
+ static char buf[1024];
+
+ int status;
+
+ memset(&pw_entry, 0, sizeof(pw_entry));
+ status = getpwnam_r(username, &pw_entry, buf, sizeof(buf), &result);
+
+ 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;
+ }
+ return result->pw_dir;
+} /* get_homedir */
static void
exit_usage(char *name, int status)
{
+ char *user = sdb_get_current_user();
printf(
"Usage: %s <options>\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 */
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 "
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;
+ sdb_llist_iter_t *iter;
+ int status = 0;
- /* needs to be static because we return a pointer into this buffer
- * to the caller */
- static char buf[1024];
-
- 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)
{
const char *host = NULL;
- const char *user = NULL;
const char *homedir;
char hist_file[1024] = "";
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;
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':
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);
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(input.client, user)) {
+ if (sdb_client_connect(input.client, input.user)) {
sdb_log(SDB_LOG_ERR, "Failed to connect to SysDBd");
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 = get_homedir(input.user))) {
snprintf(hist_file, sizeof(hist_file) - 1,
"%s/.sysdb_history", homedir);
hist_file[sizeof(hist_file) - 1] = '\0';
hist_file, sdb_strerror(errno, errbuf, sizeof(errbuf)));
}
}
+ free(input.user);
input.input = sdb_strbuf_create(2048);
sdb_input_init(&input);
- yylex();
+ sdb_input_mainloop();
+
+ 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') {
errno = 0;