diff --git a/i3-msg/main.c b/i3-msg/main.c index 131146d8..3259043c 100644 --- a/i3-msg/main.c +++ b/i3-msg/main.c @@ -36,6 +36,26 @@ static char *socket_path; +/* + * Having verboselog() and errorlog() is necessary when using libi3. + * + */ +void verboselog(char *fmt, ...) { + va_list args; + + va_start(args, fmt); + vfprintf(stdout, fmt, args); + va_end(args); +} + +void errorlog(char *fmt, ...) { + va_list args; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); +} + int main(int argc, char *argv[]) { socket_path = getenv("I3SOCK"); int o, option_index = 0; @@ -135,13 +155,16 @@ int main(int argc, char *argv[]) { return 0; uint32_t reply_length; + uint32_t reply_type; uint8_t *reply; int ret; - if ((ret = ipc_recv_message(sockfd, message_type, &reply_length, &reply)) != 0) { + if ((ret = ipc_recv_message(sockfd, &reply_type, &reply_length, &reply)) != 0) { if (ret == -1) err(EXIT_FAILURE, "IPC: read()"); exit(1); } + if (reply_type != message_type) + errx(EXIT_FAILURE, "IPC: Received reply of type %d but expected %d", reply_type, message_type); printf("%.*s\n", reply_length, reply); free(reply); diff --git a/include/libi3.h b/include/libi3.h index 2037da2e..6714cc5b 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -2,7 +2,7 @@ * vim:ts=4:sw=4:expandtab * * i3 - an improved dynamic tiling window manager - * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) + * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE) * * libi3: contains functions which are used by i3 *and* accompanying tools such * as i3-msg, i3-config-wizard, … @@ -216,7 +216,7 @@ int ipc_send_message(int sockfd, const uint32_t message_size, * Returns 0 on success. * */ -int ipc_recv_message(int sockfd, uint32_t message_type, +int ipc_recv_message(int sockfd, uint32_t *message_type, uint32_t *reply_length, uint8_t **reply); /** diff --git a/libi3/ipc_recv_message.c b/libi3/ipc_recv_message.c index f5c4a62b..8fd438e3 100644 --- a/libi3/ipc_recv_message.c +++ b/libi3/ipc_recv_message.c @@ -2,7 +2,7 @@ * vim:ts=4:sw=4:expandtab * * i3 - an improved dynamic tiling window manager - * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) + * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE) * */ #include @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -20,57 +21,56 @@ * (reply_length) as well as a pointer to its contents (reply). * * Returns -1 when read() fails, errno will remain. - * Returns -2 when the IPC protocol is violated (invalid magic, unexpected + * Returns -2 on EOF. + * Returns -3 when the IPC protocol is violated (invalid magic, unexpected * message type, EOF instead of a message). Additionally, the error will be * printed to stderr. * Returns 0 on success. * */ -int ipc_recv_message(int sockfd, uint32_t message_type, +int ipc_recv_message(int sockfd, uint32_t *message_type, uint32_t *reply_length, uint8_t **reply) { /* Read the message header first */ - uint32_t to_read = strlen(I3_IPC_MAGIC) + sizeof(uint32_t) + sizeof(uint32_t); + const uint32_t to_read = strlen(I3_IPC_MAGIC) + sizeof(uint32_t) + sizeof(uint32_t); char msg[to_read]; char *walk = msg; uint32_t read_bytes = 0; while (read_bytes < to_read) { - int n = read(sockfd, msg + read_bytes, to_read); + int n = read(sockfd, msg + read_bytes, to_read - read_bytes); if (n == -1) return -1; if (n == 0) { - fprintf(stderr, "IPC: received EOF instead of reply\n"); + ELOG("IPC: received EOF instead of reply\n"); return -2; } read_bytes += n; - to_read -= n; } if (memcmp(walk, I3_IPC_MAGIC, strlen(I3_IPC_MAGIC)) != 0) { - fprintf(stderr, "IPC: invalid magic in reply\n"); - return -2; + ELOG("IPC: invalid magic in reply\n"); + return -3; } walk += strlen(I3_IPC_MAGIC); *reply_length = *((uint32_t*)walk); walk += sizeof(uint32_t); - if (*((uint32_t*)walk) != message_type) { - fprintf(stderr, "IPC: unexpected reply type (got %d, expected %d)\n", *((uint32_t*)walk), message_type); - return -2; - } + if (message_type != NULL) + *message_type = *((uint32_t*)walk); *reply = smalloc(*reply_length); - to_read = *reply_length; read_bytes = 0; - while (read_bytes < to_read) { - int n = read(sockfd, *reply + read_bytes, to_read); - if (n == -1) + int n; + while (read_bytes < *reply_length) { + if ((n = read(sockfd, *reply + read_bytes, *reply_length - read_bytes)) == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; return -1; + } read_bytes += n; - to_read -= n; } return 0; diff --git a/src/display_version.c b/src/display_version.c index ac1a622c..0901ae07 100644 --- a/src/display_version.c +++ b/src/display_version.c @@ -101,15 +101,18 @@ void display_running_version(void) { err(EXIT_FAILURE, "IPC: write()"); uint32_t reply_length; + uint32_t reply_type; uint8_t *reply; int ret; - if ((ret = ipc_recv_message(sockfd, I3_IPC_MESSAGE_TYPE_GET_VERSION, - &reply_length, &reply)) != 0) { + if ((ret = ipc_recv_message(sockfd, &reply_type, &reply_length, &reply)) != 0) { if (ret == -1) err(EXIT_FAILURE, "IPC: read()"); exit(EXIT_FAILURE); } + if (reply_type != I3_IPC_MESSAGE_TYPE_GET_VERSION) + errx(EXIT_FAILURE, "Got reply type %d, but expected %d (GET_VERSION)", reply_type, I3_IPC_MESSAGE_TYPE_GET_VERSION); + #if YAJL_MAJOR >= 2 yajl_handle handle = yajl_alloc(&version_callbacks, NULL, NULL); #else diff --git a/src/main.c b/src/main.c index 78a84fe2..7f576d43 100644 --- a/src/main.c +++ b/src/main.c @@ -460,14 +460,16 @@ int main(int argc, char *argv[]) { err(EXIT_FAILURE, "IPC: write()"); uint32_t reply_length; + uint32_t reply_type; uint8_t *reply; int ret; - if ((ret = ipc_recv_message(sockfd, I3_IPC_MESSAGE_TYPE_COMMAND, - &reply_length, &reply)) != 0) { + if ((ret = ipc_recv_message(sockfd, &reply_type, &reply_length, &reply)) != 0) { if (ret == -1) err(EXIT_FAILURE, "IPC: read()"); return 1; } + if (reply_type != I3_IPC_MESSAGE_TYPE_COMMAND) + errx(EXIT_FAILURE, "IPC: received reply of type %d but expected %d (COMMAND)", reply_type, I3_IPC_MESSAGE_TYPE_COMMAND); printf("%.*s\n", reply_length, reply); return 0; }