X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Futils%2Funixsock.c;h=62b6f45aa404f360ed1f623c07362dcb2c2e26b0;hp=da2ca1e4a71928ab3c356d7df506d7261fab6310;hb=7eae8c92fd40a050f9ce4a7132191fbcef810dc0;hpb=170488932e1d1d77971095c4edda3969ee619d07 diff --git a/src/utils/unixsock.c b/src/utils/unixsock.c index da2ca1e..62b6f45 100644 --- a/src/utils/unixsock.c +++ b/src/utils/unixsock.c @@ -1,5 +1,5 @@ /* - * syscollector - src/utils/unixsock.c + * SysDB - src/utils/unixsock.c * Copyright (C) 2012 Sebastian 'tokkee' Harl * All rights reserved. * @@ -25,8 +25,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "utils/error.h" #include "utils/unixsock.h" -#include "utils/string.h" #include #include @@ -47,23 +47,23 @@ * private data types */ -struct sc_unixsock_client { +struct sdb_unixsock_client { char *path; FILE *fh; int shutdown; }; -#define SC_SHUT_RD (1 << SHUT_RD) -#define SC_SHUT_WR (1 << SHUT_WR) -#define SC_SHUT_RDWR (SC_SHUT_RD | SC_SHUT_WR) +#define SDB_SHUT_RD (1 << SHUT_RD) +#define SDB_SHUT_WR (1 << SHUT_WR) +#define SDB_SHUT_RDWR (SDB_SHUT_RD | SDB_SHUT_WR) /* * private helper functions */ static int -sc_unixsock_get_column_count(const char *string, const char *delim) +sdb_unixsock_get_column_count(const char *string, const char *delim) { int count = 1; @@ -85,68 +85,68 @@ sc_unixsock_get_column_count(const char *string, const char *delim) } } return count; -} /* sc_unixsock_get_column_count */ +} /* sdb_unixsock_get_column_count */ static int -sc_unixsock_parse_cell(char *string, int type, sc_data_t *data) +sdb_unixsock_parse_cell(char *string, int type, sdb_data_t *data) { char *endptr = NULL; switch (type) { - case SC_TYPE_INTEGER: + case SDB_TYPE_INTEGER: errno = 0; data->data.integer = strtoll(string, &endptr, 0); break; - case SC_TYPE_DECIMAL: + case SDB_TYPE_DECIMAL: errno = 0; data->data.decimal = strtod(string, &endptr); break; - case SC_TYPE_STRING: + case SDB_TYPE_STRING: data->data.string = string; break; - case SC_TYPE_DATETIME: + case SDB_TYPE_DATETIME: { double datetime = strtod(string, &endptr); - data->data.datetime = DOUBLE_TO_SC_TIME(datetime); + data->data.datetime = DOUBLE_TO_SDB_TIME(datetime); } break; - case SC_TYPE_BINARY: + case SDB_TYPE_BINARY: /* we don't support any binary information containing 0-bytes */ data->data.binary.length = strlen(string); data->data.binary.datum = (const unsigned char *)string; break; default: - fprintf(stderr, "unixsock: Unexpected type %i while " - "parsing query result.\n", type); + sdb_log(SDB_LOG_ERR, "unixsock: Unexpected type %i while " + "parsing query result.", type); return -1; } - if ((type == SC_TYPE_INTEGER) || (type == SC_TYPE_DECIMAL) - || (type == SC_TYPE_DATETIME)) { + if ((type == SDB_TYPE_INTEGER) || (type == SDB_TYPE_DECIMAL) + || (type == SDB_TYPE_DATETIME)) { if (errno || (string == endptr)) { char errbuf[1024]; - fprintf(stderr, "unixsock: Failed to parse string '%s' " - "as numeric value (type %i): %s\n", string, type, - sc_strerror(errno, errbuf, sizeof(errbuf))); + sdb_log(SDB_LOG_ERR, "unixsock: Failed to parse string " + "'%s' as numeric value (type %i): %s", string, type, + sdb_strerror(errno, errbuf, sizeof(errbuf))); return -1; } else if (endptr && (*endptr != '\0')) - fprintf(stderr, "unixsock: Ignoring garbage after number " - "while parsing numeric value (type %i): %s.\n", + sdb_log(SDB_LOG_WARNING, "unixsock: Ignoring garbage after " + "number while parsing numeric value (type %i): %s.", type, endptr); } data->type = type; return 0; -} /* sc_unixsock_parse_cell */ +} /* sdb_unixsock_parse_cell */ static int -sc_unixsock_client_process_one_line(sc_unixsock_client_t *client, - char *line, sc_unixsock_client_data_cb callback, - sc_object_t *user_data, const char *delim, +sdb_unixsock_client_process_one_line(sdb_unixsock_client_t *client, + char *line, sdb_unixsock_client_data_cb callback, + sdb_object_t *user_data, const char *delim, int column_count, int *types) { - sc_data_t data[column_count]; + sdb_data_t data[column_count]; char *orig_line = line; int i; @@ -157,9 +157,10 @@ sc_unixsock_client_process_one_line(sc_unixsock_client_t *client, char *next; if (! line) { /* this must no happen */ - fprintf(stderr, "unixsock: Unexpected EOL while parsing line " - "(expected %i columns delimited by '%s'; got %i): %s\n", - column_count, delim, /* last line number */ i, orig_line); + sdb_log(SDB_LOG_ERR, "unixsock: Unexpected EOL while " + "parsing line (expected %i columns delimited by '%s'; " + "got %i): %s", column_count, delim, + /* last line number */ i, orig_line); return -1; } @@ -173,8 +174,8 @@ sc_unixsock_client_process_one_line(sc_unixsock_client_t *client, ++next; } - if (sc_unixsock_parse_cell(line, - types ? types[i] : SC_TYPE_STRING, &data[i])) + if (sdb_unixsock_parse_cell(line, + types ? types[i] : SDB_TYPE_STRING, &data[i])) return -1; line = next; @@ -183,16 +184,16 @@ sc_unixsock_client_process_one_line(sc_unixsock_client_t *client, if (callback(client, (size_t)column_count, data, user_data)) return -1; return 0; -} /* sc_unixsock_client_process_one_line */ +} /* sdb_unixsock_client_process_one_line */ /* * public API */ -sc_unixsock_client_t * -sc_unixsock_client_create(const char *path) +sdb_unixsock_client_t * +sdb_unixsock_client_create(const char *path) { - sc_unixsock_client_t *client; + sdb_unixsock_client_t *client; if (! path) return NULL; @@ -205,16 +206,16 @@ sc_unixsock_client_create(const char *path) client->path = strdup(path); if (! client->path) { - sc_unixsock_client_destroy(client); + sdb_unixsock_client_destroy(client); return NULL; } client->shutdown = 0; return client; -} /* sc_unixsock_client_create */ +} /* sdb_unixsock_client_create */ int -sc_unixsock_client_connect(sc_unixsock_client_t *client) +sdb_unixsock_client_connect(sdb_unixsock_client_t *client) { struct sockaddr_un sa; int fd; @@ -230,8 +231,8 @@ sc_unixsock_client_connect(sc_unixsock_client_t *client) fd = socket(AF_UNIX, SOCK_STREAM, /* protocol = */ 0); if (fd < 0) { char errbuf[1024]; - fprintf(stderr, "unixsock: Failed to open socket: %s\n", - sc_strerror(errno, errbuf, sizeof(errbuf))); + sdb_log(SDB_LOG_ERR, "unixsock: Failed to open socket: %s", + sdb_strerror(errno, errbuf, sizeof(errbuf))); return -1; } @@ -241,8 +242,8 @@ sc_unixsock_client_connect(sc_unixsock_client_t *client) if (connect(fd, (struct sockaddr *)&sa, sizeof(sa))) { char errbuf[1024]; - fprintf(stderr, "unixsock: Failed to connect to %s: %s\n", - sa.sun_path, sc_strerror(errno, errbuf, sizeof(errbuf))); + sdb_log(SDB_LOG_ERR, "unixsock: Failed to connect to %s: %s", + sa.sun_path, sdb_strerror(errno, errbuf, sizeof(errbuf))); close(fd); return -1; } @@ -250,68 +251,85 @@ sc_unixsock_client_connect(sc_unixsock_client_t *client) client->fh = fdopen(fd, "r+"); if (! client->fh) { char errbuf[1024]; - fprintf(stderr, "unixsock: Failed to open I/O stream for %s: %s\n", - sa.sun_path, sc_strerror(errno, errbuf, sizeof(errbuf))); + sdb_log(SDB_LOG_ERR, "unixsock: Failed to open I/O " + "stream for %s: %s", sa.sun_path, + sdb_strerror(errno, errbuf, sizeof(errbuf))); close(fd); return -1; } + /* enable line-buffering */ + setvbuf(client->fh, NULL, _IOLBF, 0); + client->shutdown = 0; return 0; -} /* sc_unixsock_client_connect */ +} /* sdb_unixsock_client_connect */ int -sc_unixsock_client_send(sc_unixsock_client_t *client, const char *msg) +sdb_unixsock_client_send(sdb_unixsock_client_t *client, + const char *msg) { int status; if ((! client) || (! client->fh)) return -1; - if (client->shutdown & SC_SHUT_WR) /* reconnect */ - sc_unixsock_client_connect(client); + if (client->shutdown & SDB_SHUT_WR) /* reconnect */ + sdb_unixsock_client_connect(client); status = fprintf(client->fh, "%s\r\n", msg); if (status < 0) { char errbuf[1024]; - fprintf(stderr, "unixsock: Failed to write to socket (%s): %s\n", - client->path, sc_strerror(errno, errbuf, sizeof(errbuf))); + sdb_log(SDB_LOG_ERR, "unixsock: Failed to write to " + "socket (%s): %s", client->path, + sdb_strerror(errno, errbuf, sizeof(errbuf))); return status; } return status; -} /* sc_unixsock_client_send */ +} /* sdb_unixsock_client_send */ char * -sc_unixsock_client_recv(sc_unixsock_client_t *client, char *buffer, size_t buflen) +sdb_unixsock_client_recv(sdb_unixsock_client_t *client, + char *buffer, size_t buflen) { + char *tmp; + if ((! client) || (! client->fh) || (! buffer)) return NULL; - if (client->shutdown & SC_SHUT_RD) /* reconnect */ - sc_unixsock_client_connect(client); - - buffer = fgets(buffer, (int)buflen - 1, client->fh); - if (! buffer) { - if (! feof(client->fh)) { - char errbuf[1024]; - fprintf(stderr, "unixsock: Failed to read from socket (%s): %s\n", - client->path, sc_strerror(errno, errbuf, sizeof(errbuf))); + if (client->shutdown & SDB_SHUT_RD) /* reconnect */ + sdb_unixsock_client_connect(client); + + tmp = NULL; + while (tmp == NULL) { + errno = 0; + tmp = fgets(buffer, (int)buflen - 1, client->fh); + if (! tmp) { + if ((errno == EAGAIN) || (errno == EINTR)) + continue; + + if (! feof(client->fh)) { + char errbuf[1024]; + sdb_log(SDB_LOG_ERR, "unixsock: Failed to read " + "from socket (%s): %s", client->path, + sdb_strerror(errno, errbuf, sizeof(errbuf))); + } + return NULL; } - return buffer; } buffer[buflen - 1] = '\0'; buflen = strlen(buffer); - while ((buffer[buflen - 1] == '\n') || (buffer[buflen - 1] == '\r')) { + while (buflen && ((buffer[buflen - 1] == '\n') || (buffer[buflen - 1] == '\r'))) { buffer[buflen - 1] = '\0'; --buflen; } return buffer; -} /* sc_unixsock_client_recv */ +} /* sdb_unixsock_client_recv */ int -sc_unixsock_client_process_lines(sc_unixsock_client_t *client, - sc_unixsock_client_data_cb callback, sc_object_t *user_data, +sdb_unixsock_client_process_lines(sdb_unixsock_client_t *client, + sdb_unixsock_client_data_cb callback, sdb_object_t *user_data, long int max_lines, const char *delim, int n_cols, ...) { int *types = NULL; @@ -333,10 +351,10 @@ sc_unixsock_client_process_lines(sc_unixsock_client_t *client, for (i = 0; i < n_cols; ++i) { types[i] = va_arg(ap, int); - if ((types[i] < 1) || (types[i] > SC_TYPE_BINARY)) { - fprintf(stderr, "unixsock: Unknown column type %i while " - "processing response from the UNIX socket @ %s.\n", - types[i], client->path); + if ((types[i] < 1) || (types[i] > SDB_TYPE_BINARY)) { + sdb_log(SDB_LOG_ERR, "unixsock: Unknown column " + "type %i while processing response from the " + "UNIX socket @ %s.", types[i], client->path); va_end(ap); free(types); return -1; @@ -358,18 +376,18 @@ sc_unixsock_client_process_lines(sc_unixsock_client_t *client, if (max_lines > 0) --max_lines; - sc_unixsock_client_clearerr(client); - line = sc_unixsock_client_recv(client, buffer, sizeof(buffer)); + sdb_unixsock_client_clearerr(client); + line = sdb_unixsock_client_recv(client, buffer, sizeof(buffer)); if (! line) break; - column_count = sc_unixsock_get_column_count(line, delim); + column_count = sdb_unixsock_get_column_count(line, delim); if ((n_cols >= 0) && (n_cols != column_count)) { - fprintf(stderr, "unixsock: number of columns (%i) does not " - "match the number of requested columns (%i) while " - "processing response from the UNIX socket @ %s: %s\n", + sdb_log(SDB_LOG_ERR, "unixsock: number of columns (%i) " + "does not match the number of requested columns (%i) " + "while processing response from the UNIX socket @ %s: %s", column_count, n_cols, client->path, line); continue; } @@ -377,7 +395,7 @@ sc_unixsock_client_process_lines(sc_unixsock_client_t *client, if (column_count <= 0) /* no data */ continue; - if (! sc_unixsock_client_process_one_line(client, line, callback, + if (! sdb_unixsock_client_process_one_line(client, line, callback, user_data, delim, column_count, types)) ++success; } @@ -385,21 +403,21 @@ sc_unixsock_client_process_lines(sc_unixsock_client_t *client, free(types); if ((max_lines > 0) - || ((max_lines < 0) && (! sc_unixsock_client_eof(client))) - || sc_unixsock_client_error(client)) { + || ((max_lines < 0) && (! sdb_unixsock_client_eof(client))) + || sdb_unixsock_client_error(client)) { char errbuf[1024]; - fprintf(stderr, "unixsock: Unexpected end of data while reading " - "from socket (%s): %s\n", client->path, - sc_strerror(errno, errbuf, sizeof(errbuf))); + sdb_log(SDB_LOG_ERR, "unixsock: Unexpected end of data while " + "reading from socket (%s): %s", client->path, + sdb_strerror(errno, errbuf, sizeof(errbuf))); return -1; } if (! success) return -1; return 0; -} /* sc_unixsock_client_process_lines */ +} /* sdb_unixsock_client_process_lines */ int -sc_unixsock_client_shutdown(sc_unixsock_client_t *client, int how) +sdb_unixsock_client_shutdown(sdb_unixsock_client_t *client, int how) { int status; @@ -413,43 +431,43 @@ sc_unixsock_client_shutdown(sc_unixsock_client_t *client, int how) if (! status) { if (how == SHUT_RDWR) - client->shutdown |= SC_SHUT_RDWR; + client->shutdown |= SDB_SHUT_RDWR; else client->shutdown |= 1 << how; } return status; -} /* sc_unixsock_client_shutdown */ +} /* sdb_unixsock_client_shutdown */ void -sc_unixsock_client_clearerr(sc_unixsock_client_t *client) +sdb_unixsock_client_clearerr(sdb_unixsock_client_t *client) { if ((! client) || (! client->fh)) return; clearerr(client->fh); -} /* sc_unixsock_client_clearerr */ +} /* sdb_unixsock_client_clearerr */ int -sc_unixsock_client_eof(sc_unixsock_client_t *client) +sdb_unixsock_client_eof(sdb_unixsock_client_t *client) { if ((! client) || (! client->fh)) { errno = EBADF; return -1; } return feof(client->fh); -} /* sc_unixsock_client_eof */ +} /* sdb_unixsock_client_eof */ int -sc_unixsock_client_error(sc_unixsock_client_t *client) +sdb_unixsock_client_error(sdb_unixsock_client_t *client) { if ((! client) || (! client->fh)) { errno = EBADF; return -1; } return ferror(client->fh); -} /* sc_unixsock_client_error */ +} /* sdb_unixsock_client_error */ void -sc_unixsock_client_destroy(sc_unixsock_client_t *client) +sdb_unixsock_client_destroy(sdb_unixsock_client_t *client) { if (! client) return; @@ -463,15 +481,15 @@ sc_unixsock_client_destroy(sc_unixsock_client_t *client) client->fh = NULL; free(client); -} /* sc_unixsock_client_destroy */ +} /* sdb_unixsock_client_destroy */ const char * -sc_unixsock_client_path(sc_unixsock_client_t *client) +sdb_unixsock_client_path(sdb_unixsock_client_t *client) { if (! client) return NULL; return client->path; -} /* sc_unixsock_client_path */ +} /* sdb_unixsock_client_path */ /* vim: set tw=78 sw=4 ts=4 noexpandtab : */