From 19fb6de1c1e47c03b611ac7a0b7636b85ab20118 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 20 Jun 2020 20:34:44 +0200 Subject: Misc. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- common.h | 1 + libaxl/consts.h | 30 +++++----- libaxl/display-info.h | 2 +- libaxl/replies.h | 2 +- libaxl/requests.h | 10 ++-- libaxl/types.h | 2 +- libaxl_connect.c | 31 +++++++++- libaxl_connect_without_handshake.c | 44 +++++++++++--- libaxl_receive.c | 114 +++++++++++++++++++++++++++++-------- 9 files changed, 179 insertions(+), 57 deletions(-) diff --git a/common.h b/common.h index 5dae5a1..e0330cb 100644 --- a/common.h +++ b/common.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/libaxl/consts.h b/libaxl/consts.h index a378c73..8629651 100644 --- a/libaxl/consts.h +++ b/libaxl/consts.h @@ -274,21 +274,21 @@ #define LIBAXL_PARENT 2 /* window event mask */ -#define LIBAXL_EVENT_MASK_KEY_PRESS UINT32_C(0x00000001) -#define LIBAXL_EVENT_MASK_KEY_RELEASE UINT32_C(0x00000002) -#define LIBAXL_EVENT_MASK_BUTTON_PRESS UINT32_C(0x00000004) -#define LIBAXL_EVENT_MASK_BUTTON_RELEASE UINT32_C(0x00000008) -#define LIBAXL_EVENT_MASK_ENTER_WINDOW UINT32_C(0x00000010) -#define LIBAXL_EVENT_MASK_LEAVE_WINDOW UINT32_C(0x00000020) -#define LIBAXL_EVENT_MASK_POINTER_MOTION UINT32_C(0x00000040) -#define LIBAXL_EVENT_MASK_POINTER_MOTION_HINT UINT32_C(0x00000080) -#define LIBAXL_EVENT_MASK_BUTTON_1_MOTION UINT32_C(0x00000100) -#define LIBAXL_EVENT_MASK_BUTTON_2_MOTION UINT32_C(0x00000200) -#define LIBAXL_EVENT_MASK_BUTTON_3_MOTION UINT32_C(0x00000400) -#define LIBAXL_EVENT_MASK_BUTTON_4_MOTION UINT32_C(0x00000800) -#define LIBAXL_EVENT_MASK_BUTTON_5_MOTION UINT32_C(0x00001000) -#define LIBAXL_EVENT_MASK_BUTTON_MOTION UINT32_C(0x00002000) -#define LIBAXL_EVENT_MASK_KEYMAP_STATE UINT32_C(0x00004000) +#define LIBAXL_EVENT_MASK_KEY_PRESS UINT32_C(0x00000001) /* in SETofDEVICEEVENT */ +#define LIBAXL_EVENT_MASK_KEY_RELEASE UINT32_C(0x00000002) /* in SETofDEVICEEVENT */ +#define LIBAXL_EVENT_MASK_BUTTON_PRESS UINT32_C(0x00000004) /* in SETofDEVICEEVENT and SETofPOINTEREVENT */ +#define LIBAXL_EVENT_MASK_BUTTON_RELEASE UINT32_C(0x00000008) /* in SETofDEVICEEVENT and SETofPOINTEREVENT */ +#define LIBAXL_EVENT_MASK_ENTER_WINDOW UINT32_C(0x00000010) /* in SETofPOINTEREVENT */ +#define LIBAXL_EVENT_MASK_LEAVE_WINDOW UINT32_C(0x00000020) /* in SETofPOINTEREVENT */ +#define LIBAXL_EVENT_MASK_POINTER_MOTION UINT32_C(0x00000040) /* in SETofDEVICEEVENT and SETofPOINTEREVENT */ +#define LIBAXL_EVENT_MASK_POINTER_MOTION_HINT UINT32_C(0x00000080) /* in SETofPOINTEREVENT */ +#define LIBAXL_EVENT_MASK_BUTTON_1_MOTION UINT32_C(0x00000100) /* in SETofDEVICEEVENT and SETofPOINTEREVENT */ +#define LIBAXL_EVENT_MASK_BUTTON_2_MOTION UINT32_C(0x00000200) /* in SETofDEVICEEVENT and SETofPOINTEREVENT */ +#define LIBAXL_EVENT_MASK_BUTTON_3_MOTION UINT32_C(0x00000400) /* in SETofDEVICEEVENT and SETofPOINTEREVENT */ +#define LIBAXL_EVENT_MASK_BUTTON_4_MOTION UINT32_C(0x00000800) /* in SETofDEVICEEVENT and SETofPOINTEREVENT */ +#define LIBAXL_EVENT_MASK_BUTTON_5_MOTION UINT32_C(0x00001000) /* in SETofDEVICEEVENT and SETofPOINTEREVENT */ +#define LIBAXL_EVENT_MASK_BUTTON_MOTION UINT32_C(0x00002000) /* in SETofDEVICEEVENT and SETofPOINTEREVENT */ +#define LIBAXL_EVENT_MASK_KEYMAP_STATE UINT32_C(0x00004000) /* in SETofPOINTEREVENT */ #define LIBAXL_EVENT_MASK_EXPOSURE UINT32_C(0x00008000) #define LIBAXL_EVENT_MASK_VISIBILITY_CHANGE UINT32_C(0x00010000) #define LIBAXL_EVENT_MASK_STRUCTURE_NOTIFY UINT32_C(0x00020000) diff --git a/libaxl/display-info.h b/libaxl/display-info.h index f01ade1..75285ac 100644 --- a/libaxl/display-info.h +++ b/libaxl/display-info.h @@ -113,7 +113,7 @@ struct libaxl_screen { */ uint32_t black_pixel; - uint32_t current_input_masks; /* TODO SETofEVENTS */ + uint32_t current_input_masks; /* See "window event mask" in "consts.h" */ /* TODO doc */ /** * The width, in pixels, of the root window; diff --git a/libaxl/replies.h b/libaxl/replies.h index c8de403..8c48047 100644 --- a/libaxl/replies.h +++ b/libaxl/replies.h @@ -24,7 +24,7 @@ struct libaxl_reply_get_window_attributes { libaxl_colormap_t colormap; /* Can be LIBAXL_NONE */ uint32_t all_event_masks; /* See "window event mask" in "consts.h" */ uint32_t your_event_mask; /* See "window event mask" in "consts.h" */ - uint16_t do_not_propagate_mask; /* TODO SETofDEVICEEVENT */ + uint16_t do_not_propagate_mask; /* See SETofDEVICEEVENT in "consts.h" */ uint16_t __pad; }; diff --git a/libaxl/requests.h b/libaxl/requests.h index dffb904..27ba705 100644 --- a/libaxl/requests.h +++ b/libaxl/requests.h @@ -48,7 +48,7 @@ struct libaxl_request_create_window { libaxl_bool_t save_under; uint16_t __omitted2; uint32_t event_mask; /* See "window event mask" in "consts.h" */ - uint32_t do_not_propagate_mask; /* TODO SETofDEVICEEVENT */ + uint32_t do_not_propagate_mask; /* See SETofDEVICEEVENT in "consts.h" */ libaxl_colormap_t colormap; /* Can be LIBAXL_COPY_FROM_PARENT */ libaxl_cursor_t cursor; /* Can be LIBAXL_NONE */ }; @@ -89,7 +89,7 @@ struct libaxl_request_change_window_attributes { libaxl_bool_t save_under; uint16_t __omitted2; uint32_t event_mask; /* See "window event mask" in "consts.h" */ - uint32_t do_not_propagate_mask; /* TODO SETofDEVICEEVENT */ + uint32_t do_not_propagate_mask; /* See SETofDEVICEEVENT in "consts.h" */ libaxl_colormap_t colormap; /* Can be LIBAXL_COPY_FROM_PARENT */ libaxl_cursor_t cursor; /* Can be LIBAXL_NONE */ }; @@ -330,7 +330,7 @@ struct libaxl_request_grab_pointer { libaxl_bool_t owner_events; uint16_t _request_length; /* = 6 */ libaxl_window_t grab_window; - uint16_t event_mask; /* TODO SETofPOINTEREVENT */ + uint16_t event_mask; /* See SETofPOINTEREVENT in "consts.h" */ uint8_t pointer_mode; /* LIBAXL_{SYNCHRONOUS or ASYNCHRONOUS} */ uint8_t keyboard_mode; /* LIBAXL_{SYNCHRONOUS or ASYNCHRONOUS} */ libaxl_window_t confine_to; /* Can be LIBAXL_NONE */ @@ -352,7 +352,7 @@ struct libaxl_request_grab_button { uint8_t __pad1; uint16_t _request_length; /* = 6 */ libaxl_window_t grab_window; - uint16_t event_mask; /* TODO SETofPOINTEREVENT */ + uint16_t event_mask; /* See SETofPOINTEREVENT in "consts.h" */ uint8_t pointer_mode; /* LIBAXL_{SYNCHRONOUS or ASYNCHRONOUS} */ uint8_t keyboard_mode; /* LIBAXL_{SYNCHRONOUS or ASYNCHRONOUS} */ libaxl_window_t confine_to; /* Can be LIBAXL_NONE */ @@ -379,7 +379,7 @@ struct libaxl_request_change_active_pointer_grab { uint16_t _request_length; /* = 4 */ libaxl_cursor_t cursor; /* Can be LIBAXL_NONE */ libaxl_timestamp_t time; /* Can be LIBAXL_CURRENT_TIME */ - uint16_t event_mask; /* TODO SETofPOINTEREVENT */ + uint16_t event_mask; /* See SETofPOINTEREVENT in "consts.h" */ uint16_t __pad2; }; diff --git a/libaxl/types.h b/libaxl/types.h index f30c434..ad44576 100644 --- a/libaxl/types.h +++ b/libaxl/types.h @@ -105,7 +105,7 @@ struct libaxl_timecoord { struct libaxl_fontprop { libaxl_atom_t name; - uint32_t value; /* <32-bits> */ + uint32_t value; /* <32 bits> */ }; struct libaxl_charinfo { diff --git a/libaxl_connect.c b/libaxl_connect.c index ee4edd8..529295d 100644 --- a/libaxl_connect.c +++ b/libaxl_connect.c @@ -13,11 +13,36 @@ static char * path_in_home(const char *filename) { const char *home; - char *ret; + struct passwd *pwd, pwd_buf; + size_t buf_size; + char *buf, *ret; + int r; home = getenv("HOME"); - if (!home || !*home) { /* TODO */ - abort(); + if (!home || !*home) { + buf_size = sysconf(_SC_GETPW_R_SIZE_MAX); + buf_size = buf_size == -1 ? 16384 : buf_size; + buf = alloca(buf_size); + r = getpwuid_r(getuid(), &pwd_buf, buf, buf_size, &pwd); + if (!pwd) { + liberror_save_backtrace(NULL); + r = (r == ENOENT || r == ESRCH || r == EBADF || r == EPERM || r == EIO /* glibc bug */) ? 0 : r; + if (r) { + liberror_set_error_errno(strerror(r), "getpwuid_r", r); + } else { + liberror_set_error_errno("User does not exist", "getpwuid_r", "libaxl", + LIBAXL_ERROR_USER_DOES_NOT_EXIST); + } + return NULL; + } else { + home = pwd->pw_dir; + if (!home || !*home) { + liberror_save_backtrace(NULL); + liberror_set_error_errno("User does not have a home", "libaxl_connect", "libaxl", + LIBAXL_ERROR_USER_DOES_NOT_HAVE_A_HOME); + return NULL; + } + } } ret = liberror_malloc(strlen(home) + strlen(filename) + 2); diff --git a/libaxl_connect_without_handshake.c b/libaxl_connect_without_handshake.c index e05dd66..5a4d1d8 100644 --- a/libaxl_connect_without_handshake.c +++ b/libaxl_connect_without_handshake.c @@ -52,21 +52,51 @@ connect_unix(const char *path) return fd; } +static int +connect_unix_abstract(const char *path, size_t len) +{ + struct sockaddr_un addr; + int fd; + + fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (fd < 0) { + liberror_save_backtrace(NULL); + liberror_set_error_errno(strerror(errno), "socket", errno); + return -1; + } + + addr.sun_family = AF_LOCAL; + memcpy(addr.sun_path, path, len); + if (connect(fd, (void *)&addr, (socklen_t)len)) { + liberror_save_backtrace(NULL); + liberror_set_error_errno(strerror(errno), "connect", errno); + return -1; + } + + return fd; +} + LIBAXL_CONNECTION * libaxl_connect_without_handshake(const char *host, const char *protocol, int display, int screen) { LIBAXL_CONNECTION *conn; - char path[sizeof("/tmp/.X11-unix/X-") + 3 * sizeof(int)]; - int fd; + char path[sizeof("@/tmp/.X11-unix/X-") + 3 * sizeof(int)]; + int fd, len; if ((!protocol || !*protocol) && (!host || !*host)) { - sprintf(path, "/tmp/.X11-unix/X%i", display); - fd = connect_unix(path); - /* TODO also try abstract address version with a NUL byte before it (truncate address to remove tailing NULs) */ + len = sprintf(path, "%c/tmp/.X11-unix/X%i", 0, display); + fd = connect_unix(&path[1]); if (fd < 0) { - fd = connect_tcp_ip("localhost", display); - if (fd >= 0) + fd = connect_unix_abstract(path, (size_t)len); + if (fd >= 0) { liberror_pop_error(); + } else { + fd = connect_tcp_ip("localhost", display); + if (fd >= 0) { + liberror_pop_error(); + liberror_pop_error(); + } + } } } else if (!protocol || !*protocol || diff --git a/libaxl_receive.c b/libaxl_receive.c index 2e4fc20..227e149 100644 --- a/libaxl_receive.c +++ b/libaxl_receive.c @@ -60,12 +60,13 @@ static const char *const reply_formats[] = { * $ = previous marked length, in units * % = previous marked format, in bits * @ = non-encoded size_t length marked, align output to (size_t) - * u = STRING8, align output to (void *) and enter - * U = STRING16, align output to (void *) and enter + * u = STRING8, align output to (void *) and enter (equivalent to "*1/") + * U = STRING16, align output to (void *) and enter (equivalent to "*2/") * d = data, uses %, align output to (void *) and enter * * = following are repeated, align output to (void *) and enter * & = * but requires allocation - * p = padding + * / = end of * or & + * p = padding, align input to byte-quad */ [0] = NULL, [LIBAXL_REQUEST_CREATE_WINDOW] = NULL, @@ -82,13 +83,13 @@ static const char *const reply_formats[] = { [LIBAXL_REQUEST_CONFIGURE_WINDOW] = NULL, [LIBAXL_REQUEST_CIRCULATE_WINDOW] = NULL, [LIBAXL_REQUEST_GET_GEOMETRY] = "1244ss222", - [LIBAXL_REQUEST_QUERY_TREE] = "1.24442$=-,*4", + [LIBAXL_REQUEST_QUERY_TREE] = "1.24442$=-,*4/", [LIBAXL_REQUEST_INTERN_ATOM] = "1.244", [LIBAXL_REQUEST_GET_ATOM_NAME] = "1.242$==-,u", [LIBAXL_REQUEST_CHANGE_PROPERTY] = NULL, [LIBAXL_REQUEST_DELETE_PROPERTY] = NULL, [LIBAXL_REQUEST_GET_PROPERTY] = "11%24444$=-d", - [LIBAXL_REQUEST_LIST_PROPERTIES] = "1.242$==-,*4", + [LIBAXL_REQUEST_LIST_PROPERTIES] = "1.242$==-,*4/", [LIBAXL_REQUEST_SET_SELECTION_OWNER] = NULL, [LIBAXL_REQUEST_GET_SELECTION_OWNER] = "1.244", [LIBAXL_REQUEST_CONVERT_SELECTION] = NULL, @@ -106,7 +107,7 @@ static const char *const reply_formats[] = { [LIBAXL_REQUEST_GRAB_SERVER] = NULL, [LIBAXL_REQUEST_UNGRAB_SERVER] = NULL, [LIBAXL_REQUEST_QUERY_POINTER] = ".!2444ssss2", - [LIBAXL_REQUEST_GET_MOTION_EVENTS] = "1!244$==-*4ss", + [LIBAXL_REQUEST_GET_MOTION_EVENTS] = "1!244$==-*4ss/", [LIBAXL_REQUEST_TRANSLATE_COORDINATES] = "1!244ss", [LIBAXL_REQUEST_WARP_POINTER] = NULL, [LIBAXL_REQUEST_SET_INPUT_FOCUS] = "11244", @@ -114,12 +115,12 @@ static const char *const reply_formats[] = { [LIBAXL_REQUEST_QUERY_KEYMAP] = "1.24#", [LIBAXL_REQUEST_OPEN_FONT] = NULL, [LIBAXL_REQUEST_CLOSE_FONT] = NULL, - [LIBAXL_REQUEST_QUERY_FONT] = "1.24sssss2-sssss2-2222$111!ss4$*44*sssss2", + [LIBAXL_REQUEST_QUERY_FONT] = "1.24sssss2-sssss2-2222$111!ss4$*44/*sssss2/", [LIBAXL_REQUEST_QUERY_TEXT_EXTENTS] = "1124ssssSSS", - [LIBAXL_REQUEST_LIST_FONTS] = "1.242$==-,&1$u", - [LIBAXL_REQUEST_LIST_FONTS_WITH_INFO] = "11$24?sssss2-sssss2-2222$?111!ss4*44u", + [LIBAXL_REQUEST_LIST_FONTS] = "1.242$==-,&1$u/", + [LIBAXL_REQUEST_LIST_FONTS_WITH_INFO] = "11$24?sssss2-sssss2-2222$?111!ss4*44/u", [LIBAXL_REQUEST_SET_FONT_PATH] = NULL, - [LIBAXL_REQUEST_GET_FONT_PATH] = "1.242$==-,&1$u", + [LIBAXL_REQUEST_GET_FONT_PATH] = "1.242$==-,&1$u/", [LIBAXL_REQUEST_CREATE_PIXMAP] = NULL, [LIBAXL_REQUEST_FREE_PIXMAP] = NULL, [LIBAXL_REQUEST_CREATE_GC] = NULL, @@ -140,7 +141,7 @@ static const char *const reply_formats[] = { [LIBAXL_REQUEST_POLY_FILL_RECTANGLE] = NULL, [LIBAXL_REQUEST_POLY_FILL_ARC] = NULL, [LIBAXL_REQUEST_PUT_IMAGE] = NULL, - [LIBAXL_REQUEST_GET_IMAGE] = "11244==-@u", /* "u" is actually "*1" */ + [LIBAXL_REQUEST_GET_IMAGE] = "11244==-@u", [LIBAXL_REQUEST_POLY_TEXT8] = NULL, [LIBAXL_REQUEST_POLY_TEXT16] = NULL, [LIBAXL_REQUEST_IMAGE_TEXT8] = NULL, @@ -150,15 +151,15 @@ static const char *const reply_formats[] = { [LIBAXL_REQUEST_COPY_COLORMAP_AND_FREE] = NULL, [LIBAXL_REQUEST_INSTALL_COLORMAP] = NULL, [LIBAXL_REQUEST_UNINSTALL_COLORMAP] = NULL, - [LIBAXL_REQUEST_LIST_INSTALLED_COLORMAPS] = "1.242$==-,*4", + [LIBAXL_REQUEST_LIST_INSTALLED_COLORMAPS] = "1.242$==-,*4/", [LIBAXL_REQUEST_ALLOC_COLOR] = "1.24222,4", [LIBAXL_REQUEST_ALLOC_NAMED_COLOR] = "1.244222222", - [LIBAXL_REQUEST_ALLOC_COLOR_CELLS] = "1.242$2$==-*4*4", + [LIBAXL_REQUEST_ALLOC_COLOR_CELLS] = "1.242$2$==-*4/*4/", [LIBAXL_REQUEST_ALLOC_COLOR_PLANES] = "1.242$,444=*4", [LIBAXL_REQUEST_FREE_COLORS] = NULL, [LIBAXL_REQUEST_STORE_COLORS] = NULL, [LIBAXL_REQUEST_STORE_NAMED_COLOR] = NULL, - [LIBAXL_REQUEST_QUERY_COLORS] = "1.242$==-,*222,", + [LIBAXL_REQUEST_QUERY_COLORS] = "1.242$==-,*222,/", [LIBAXL_REQUEST_LOOKUP_COLOR] = "1.24222222", [LIBAXL_REQUEST_CREATE_CURSOR] = NULL, [LIBAXL_REQUEST_CREATE_GLYPH_CURSOR] = NULL, @@ -166,9 +167,9 @@ static const char *const reply_formats[] = { [LIBAXL_REQUEST_RECOLOR_CURSOR] = NULL, [LIBAXL_REQUEST_QUERY_BEST_SIZE] = "1.2422", [LIBAXL_REQUEST_QUERY_EXTENSION] = "1.24!1111", - [LIBAXL_REQUEST_LIST_EXTENSIONS] = "11$24===&1$u", + [LIBAXL_REQUEST_LIST_EXTENSIONS] = "11$24===&1$u/", [LIBAXL_REQUEST_CHANGE_KEYBOARD_MAPPING] = NULL, - [LIBAXL_REQUEST_GET_KEYBOARD_MAPPING] = "1124$===*4", + [LIBAXL_REQUEST_GET_KEYBOARD_MAPPING] = "1124$===*4/", [LIBAXL_REQUEST_CHANGE_KEYBOARD_CONTROL] = NULL, [LIBAXL_REQUEST_GET_KEYBOARD_CONTROL] = "112441122,#", [LIBAXL_REQUEST_BELL] = NULL, @@ -177,16 +178,16 @@ static const char *const reply_formats[] = { [LIBAXL_REQUEST_SET_SCREEN_SAVER] = NULL, [LIBAXL_REQUEST_GET_SCREEN_SAVER] = "1.242211", [LIBAXL_REQUEST_CHANGE_HOSTS] = NULL, - [LIBAXL_REQUEST_LIST_HOSTS] = "1124$2==-,&1.2$up", /* "u" is actually "*1" */ + [LIBAXL_REQUEST_LIST_HOSTS] = "1124$2==-,&1.2$up/", [LIBAXL_REQUEST_SET_ACCESS_CONTROL] = NULL, [LIBAXL_REQUEST_SET_CLOSE_DOWN_MODE] = NULL, [LIBAXL_REQUEST_KILL_CLIENT] = NULL, [LIBAXL_REQUEST_ROTATE_PROPERTIES] = NULL, [LIBAXL_REQUEST_FORCE_SCREEN_SAVER] = NULL, [LIBAXL_REQUEST_SET_POINTER_MAPPING] = "1124", - [LIBAXL_REQUEST_GET_POINTER_MAPPING] = "11$24===*1", + [LIBAXL_REQUEST_GET_POINTER_MAPPING] = "11$24===*1/", [LIBAXL_REQUEST_SET_MODIFIER_MAPPING] = "1124", - [LIBAXL_REQUEST_GET_MODIFIER_MAPPING] = "11$24===*11", + [LIBAXL_REQUEST_GET_MODIFIER_MAPPING] = "11$24===*11/", [LIBAXL_REQUEST_NO_OPERATION] = NULL }; @@ -194,11 +195,17 @@ static const char *const reply_formats[] = { int libaxl_receive(LIBAXL_CONTEXT *restrict ctx, union libaxl_input *restrict msgp, int flags) { + struct { + const char *fmt; + char *msg; + size_t ic, oc, o, count; + } stack[3]; + size_t si = 0; LIBAXL_CONNECTION *conn = ctx->conn; const char *fmt; char *restrict msg = (char *)msgp; char *restrict inbuf, *data; - size_t format = 1, counts[] = {0, 0, 0}, count; + size_t format = 1, counts[] = {0, 0, 0}, count = 0; ssize_t r; uint64_t n, u64; uint8_t code; @@ -418,7 +425,7 @@ received_reply: return LIBAXL_ERROR_INVALID_REPLY_OPCODE; } - for (i = o = 0; i < n; fmt++) { + for (i = o = 0; i < n || *fmt == '@' || *fmt == '$' || *fmt == '%' || *fmt == '/'; fmt++) { switch (*fmt) { case '\0': goto end_of_fmt; @@ -575,10 +582,19 @@ received_reply: case '*': ALIGN(&o, void *); *(void **)&msg[o] = data = &inbuf[i]; + o += sizeof(void *); + stack[si].fmt = fmt; + stack[si].msg = msg; + stack[si].ic = ic; + stack[si].oc = oc + 1; + stack[si].o = o; + stack[si].count = count; + si += 1; count = counts[oc++]; - /* TODO */ - fprintf(stderr, "libaxl_receive: function not fully implemented: '*' case\n"); - abort(); + o = 0; + msg = data; + if (!count) + goto jump_to_end_of_repeat; break; case '&': /* TODO */ @@ -592,6 +608,32 @@ received_reply: */ break; + case '/': + if (--count) { + fmt = stack[si - 1].fmt; + } else { + if (0) { + jump_to_end_of_repeat: + for (j = 0;; fmt++) { + if (*fmt == '*' || *fmt == '&') { + j += 1; + } else if (*fmt == '/') { + if (!j--) + break; + } else if (!*fmt) { + abort(); + } + } + } + si -= 1; + msg = stack[si].msg; + ic = stack[si].ic; + oc = stack[si].oc; + o = stack[si].o; + count = stack[si].count; + } + break; + case '?': /* We know that code == LIBAXL_REQUEST_LIST_FONTS_WITH_INFO */ if (!qc++) { @@ -609,6 +651,30 @@ received_reply: } } + for (; *fmt && oc < ic && !counts[oc++]; fmt++) { + if (*fmt == '*' || *fmt == '&') { + ALIGN(&o, void *); + *(void **)&msg[o] = NULL; + o += sizeof(void *); + for (j = 0;; fmt++) { + if (*fmt == '*' || *fmt == '&') { + j += 1; + } else if (*fmt == '/') { + if (!--j) + break; + } else if (!*fmt) { + abort(); + } + } + } else if (*fmt == 'u' || *fmt == 'U' || *fmt == 'd') { + ALIGN(&o, void *); + *(void **)&msg[o] = NULL; + o += sizeof(void *); + } else { + break; + } + } + if (*fmt) { liberror_save_backtrace(NULL); short_msg: -- cgit v1.2.3-70-g09d2