aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mds-kkbd.c51
1 files changed, 35 insertions, 16 deletions
diff --git a/src/mds-kkbd.c b/src/mds-kkbd.c
index dc0356e..3319c87 100644
--- a/src/mds-kkbd.c
+++ b/src/mds-kkbd.c
@@ -798,7 +798,7 @@ int handle_keyboard_enumeration(const char* recv_modify_id)
the buffer. */
fail_if (ensure_send_buffer_size(n + 1) < 0);
- /* Fetch and increment local message ID. */
+ /* Fetch and increase local message ID. */
with_mutex (send_mutex,
msgid = message_id;
message_id = message_id == INT32_MAX ? 0 : (message_id + 1);
@@ -1307,50 +1307,69 @@ static int remap(char* table, size_t n)
* @param recv_message_id The value of the `Message ID`-header
* @return Zero on success, -1 on error
*/
-static int mapping_query(const char* recv_client_id, const char* recv_message_id) /* TODO proofread */
+static int mapping_query(const char* recv_client_id, const char* recv_message_id)
{
size_t top = 64 + 3 * sizeof(size_t), n = 0, off, i;
- int greatest = (int)mapping_size, r;
+ ssize_t len;
+ int greatest = 0, r;
uint32_t msgid;
+ /* Count the number of non-identity mappings, and
+ figure out the value of non-identity mapping
+ with the highest value. */
for (i = 0; i < mapping_size; i++)
if (mapping[i] != (int)i)
{
greatest = max(greatest, mapping[i]);
n++;
}
-
- n *= 3 + (size_t)(greatest > 0x00FF ? 5 : 3);
-
+ /* If the highest source is larger than the
+ highest targt, that source value will
+ be highest integer that will be included
+ the mapping-table. */
+ greatest = max(greatest, (int)mapping_size);
+ /* Calculate an upper bound for the payload. */
+ n *= 2 + 2 * (size_t)(greatest > 0x00FF ? 5 : 3);
+
+ /* Ensure that the buffer is large enough for
+ the message and that `sprintf` will not
+ write outside it. */
fail_if (ensure_send_buffer_size(top + n + 2) < 0);
+ /* Fetch and increase local message ID. */
with_mutex (send_mutex,
msgid = message_id;
message_id = message_id == INT32_MAX ? 0 : (message_id + 1);
);
+ /* The offset for the payload should fit all
+ headers and an empty line. */
off = top + 1;
+ /* Write all non-identity mappings to the payload. */
for (i = 0; i < mapping_size; i++)
if (mapping[i] != (int)i)
- {
- sprintf(send_buffer + off, "%i %i\n", i, mapping[i]);
- off += strlen(send_buffer + off);
- }
-
+ sprintf(send_buffer + off, "%i %i\n%zn", i, mapping[i], &len),
+ off += (size_t)len;
+ /* Calculate the length of the payload. */
n = (size_t)(off - (top + 1));
+ /* Write the headers, and the empty line after them. */
sprintf(send_buffer,
"To: %s\n"
"In response to: %s\n"
"Message ID: %" PRIu32 "\n"
"Length: %zu\n"
- "\n",
- recv_client_id, recv_message_id, msgid, n);
-
- off = top + 1;
- off -= top = strlen(send_buffer);
+ "\n%zn",
+ recv_client_id, recv_message_id, msgid, n, &len);
+ top = (size_t)len;
+ /* Move the headers and the empty line so that they are
+ juxtaposed with the payload. */
+ off -= top;
memmove(send_buffer + off, send_buffer, top * sizeof(char));
+
+ /* Send the message. */
+
with_mutex (send_mutex,
r = full_send(send_buffer + off, top + n);
if (r) r = errno ? errno : -1;