X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Fclient%2Fsock.c;h=b60bad45e2cf97d47d2c101513c030f4a27fff5e;hp=ffabdc1b74add0a1a7d09c0575ccf36a1ef59115;hb=56b97a180a53aecbfe9f7162b8ece3faae973cf9;hpb=7201fdaa25c85da9321591694901a5f0dfaa04a6 diff --git a/src/client/sock.c b/src/client/sock.c index ffabdc1..b60bad4 100644 --- a/src/client/sock.c +++ b/src/client/sock.c @@ -25,7 +25,12 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + #include "client/sock.h" +#include "utils/error.h" #include "utils/strbuf.h" #include "utils/proto.h" @@ -51,6 +56,7 @@ struct sdb_client { char *address; int fd; + _Bool eof; }; /* @@ -63,15 +69,22 @@ connect_unixsock(sdb_client_t *client, const char *address) struct sockaddr_un sa; client->fd = socket(AF_UNIX, SOCK_STREAM, /* protocol = */ 0); - if (client->fd < 0) + if (client->fd < 0) { + char errbuf[1024]; + sdb_log(SDB_LOG_ERR, "Failed to open socket: %s", + sdb_strerror(errno, errbuf, sizeof(errbuf))); return -1; + } sa.sun_family = AF_UNIX; strncpy(sa.sun_path, address, sizeof(sa.sun_path)); sa.sun_path[sizeof(sa.sun_path) - 1] = '\0'; if (connect(client->fd, (struct sockaddr *)&sa, sizeof(sa))) { + char errbuf[1024]; sdb_client_close(client); + sdb_log(SDB_LOG_ERR, "Failed to connect to '%s': %s", + sa.sun_path, sdb_strerror(errno, errbuf, sizeof(errbuf))); return -1; } return client->fd; @@ -90,14 +103,18 @@ sdb_client_create(const char *address) return NULL; client = malloc(sizeof(*client)); - if (! client) + if (! client) { + sdb_log(SDB_LOG_ERR, "Out of memory"); return NULL; + } memset(client, 0, sizeof(*client)); client->fd = -1; + client->eof = 1; client->address = strdup(address); if (! client->address) { sdb_client_destroy(client); + sdb_log(SDB_LOG_ERR, "Out of memory"); return NULL; } @@ -120,8 +137,12 @@ sdb_client_destroy(sdb_client_t *client) } /* sdb_client_destroy */ int -sdb_client_connect(sdb_client_t *client) +sdb_client_connect(sdb_client_t *client, const char *username) { + sdb_strbuf_t *buf; + ssize_t status; + uint32_t rstatus; + if ((! client) || (! client->address)) return -1; @@ -132,14 +153,80 @@ sdb_client_connect(sdb_client_t *client) connect_unixsock(client, client->address + strlen("unix:")); else if (*client->address == '/') connect_unixsock(client, client->address); - else + else { + sdb_log(SDB_LOG_ERR, "Unknown address type: %s", client->address); return -1; + } if (client->fd < 0) return -1; - return 0; + client->eof = 0; + + /* XXX */ + if (! username) + username = ""; + + status = sdb_client_send(client, CONNECTION_STARTUP, + (uint32_t)strlen(username), username); + if (status < 0) { + char errbuf[1024]; + sdb_client_close(client); + sdb_log(SDB_LOG_ERR, "Failed to send STARTUP message to server: %s", + sdb_strerror(errno, errbuf, sizeof(errbuf))); + return (int)status; + } + + buf = sdb_strbuf_create(64); + rstatus = 0; + status = sdb_client_recv(client, &rstatus, buf); + if ((status > 0) && (rstatus == CONNECTION_OK)) { + sdb_strbuf_destroy(buf); + return 0; + } + + if (status < 0) { + char errbuf[1024]; + sdb_log(SDB_LOG_ERR, "Failed to receive server response: %s", + sdb_strerror(errno, errbuf, sizeof(errbuf))); + } + else if (client->eof) + sdb_log(SDB_LOG_ERR, "Encountered end-of-file while waiting " + "for server response"); + + if (rstatus != CONNECTION_OK) { + sdb_log(SDB_LOG_ERR, "Access denied for user '%s'", username); + status = -((int)rstatus); + } + + sdb_client_close(client); + sdb_strbuf_destroy(buf); + return (int)status; } /* sdb_client_connect */ +int +sdb_client_sockfd(sdb_client_t *client) +{ + if (! client) + return -1; + return client->fd; +} /* sdb_client_sockfd */ + +int +sdb_client_shutdown(sdb_client_t *client, int how) +{ + if (! client) { + errno = ENOTSOCK; + return -1; + } + + if (client->fd < 0) { + errno = EBADF; + return -1; + } + + return shutdown(client->fd, how); +} /* sdb_client_shutdown */ + void sdb_client_close(sdb_client_t *client) { @@ -148,6 +235,7 @@ sdb_client_close(sdb_client_t *client) close(client->fd); client->fd = -1; + client->eof = 1; } /* sdb_client_close */ ssize_t @@ -172,26 +260,31 @@ sdb_client_recv(sdb_client_t *client, size_t data_offset = sdb_strbuf_len(buf); + if (code) + *code = UINT32_MAX; + if ((! client) || (! client->fd) || (! buf)) { errno = EBADF; return -1; } - if (code) - *code = UINT32_MAX; - while (42) { ssize_t status; + if (sdb_proto_select(client->fd, SDB_PROTO_SELECTIN)) + return -1; + errno = 0; status = sdb_strbuf_read(buf, client->fd, req); if (status < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) - break; + continue; return status; } - else if (! status) /* EOF */ + else if (! status) { + client->eof = 1; break; + } total += (size_t)status; @@ -213,11 +306,29 @@ sdb_client_recv(sdb_client_t *client, break; } + if (total != req) { + /* unexpected EOF; clear partially read data */ + sdb_strbuf_skip(buf, data_offset, sdb_strbuf_len(buf)); + return 0; + } + + if (rstatus != UINT32_MAX) + /* remove status,len */ + sdb_strbuf_skip(buf, data_offset, 2 * sizeof(rstatus)); + if (code) *code = rstatus; return (ssize_t)total; } /* sdb_client_recv */ +_Bool +sdb_client_eof(sdb_client_t *client) +{ + if ((! client) || (client->fd < 0)) + return 1; + return client->eof; +} /* sdb_client_eof */ + /* vim: set tw=78 sw=4 ts=4 noexpandtab : */