/** Sends or receives a string to or from the current network package. * \param str When encoding a packet this is the (NUL-terminated string to * be sent in the current network package. When decoding this * is the buffer to decode the string from the network package * into. When decoding this string is guaranteed to be * NUL-terminated provided that this buffer is at least 1 byte * large. * \param maxlen The buffer size of \c str. For static buffers this means * sizeof(\c str), for dynamically allocated buffers this is * whatever number you passed to malloc(). * \note If while decoding \c maxlen is smaller than the actual length of the * string being decoded, the resulting string (in \c str) will be * truncated. */ BOOL NETstring(char *str, uint16_t maxlen) { /* * Strings sent over the network are prefixed with their length, sent as an * unsigned 16-bit integer. */ // Work out the length of the string if we are encoding uint16_t len = (NETgetPacketDir() == PACKET_ENCODE) ? strnlen1(str, maxlen) : 0; char *store; // Add/fetch the length from the packet NETuint16_t(&len); // Map store to the message buffer store = (char *) &NetMsg.body[NetMsg.size]; // Make sure there is enough data/space left in the packet if (len + NetMsg.size > sizeof(NetMsg.body) || !NetMsg.status) { return NetMsg.status = false; } if (NETgetPacketDir() == PACKET_ENCODE) { memcpy(store, str, len); } else if (NETgetPacketDir() == PACKET_DECODE) { // Truncate length if necessary if (len > maxlen) { debug(LOG_ERROR, "NETstring: Decoding packet type %d from %d, buffer size %u truncated at %u", NetMsg.type, NetMsg.source, len, maxlen); len = maxlen; } memcpy(str, store, len); // Guarantee NUL-termination str[len - 1] = '\0'; } // Increment the size of the message NetMsg.size += sizeof(len) + len; return true; }
size_t mbsrtowcs (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps) { if (ps == NULL) ps = &_gl_mbsrtowcs_state; { const char *src = *srcp; if (dest != NULL) { wchar_t *destptr = dest; for (; len > 0; destptr++, len--) { size_t src_avail; size_t ret; /* An optimized variant of src_avail = strnlen1 (src, MB_LEN_MAX); */ if (src[0] == '\0') src_avail = 1; else if (src[1] == '\0') src_avail = 2; else if (src[2] == '\0') src_avail = 3; else if (MB_LEN_MAX <= 4 || src[3] == '\0') src_avail = 4; else src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4); /* Parse the next multibyte character. */ ret = mbrtowc (destptr, src, src_avail, ps); if (ret == (size_t)(-2)) /* Encountered a multibyte character that extends past a '\0' byte or that is longer than MB_LEN_MAX bytes. Cannot happen. */ abort (); if (ret == (size_t)(-1)) goto bad_input; if (ret == 0) { src = NULL; /* Here mbsinit (ps). */ break; } src += ret; } *srcp = src; return destptr - dest; } else { /* Ignore dest and len, don't store *srcp at the end, and don't clobber *ps. */ mbstate_t state = *ps; size_t totalcount = 0; for (;; totalcount++) { size_t src_avail; size_t ret; /* An optimized variant of src_avail = strnlen1 (src, MB_LEN_MAX); */ if (src[0] == '\0') src_avail = 1; else if (src[1] == '\0') src_avail = 2; else if (src[2] == '\0') src_avail = 3; else if (MB_LEN_MAX <= 4 || src[3] == '\0') src_avail = 4; else src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4); /* Parse the next multibyte character. */ ret = mbrtowc (NULL, src, src_avail, &state); if (ret == (size_t)(-2)) /* Encountered a multibyte character that extends past a '\0' byte or that is longer than MB_LEN_MAX bytes. Cannot happen. */ abort (); if (ret == (size_t)(-1)) goto bad_input2; if (ret == 0) { /* Here mbsinit (&state). */ break; } src += ret; } return totalcount; } bad_input: *srcp = src; bad_input2: errno = EILSEQ; return (size_t)(-1); } }