#include "precompile.h" #include "toolkit.h" #include "strutil.h" #ifndef _WIN32 #include #endif //NOT _WIN32 #define TAG TOOLKIT_TAG("main") #if 0 static int inet_ntop4(const unsigned char* src, char* dst, size_t size); static int inet_ntop6(const unsigned char* src, char* dst, size_t size); int toolkit_inet_ntop(int af, const void* src, char* dst, size_t size) { switch (af) { case AF_INET: return (inet_ntop4(src, dst, size)); case AF_INET6: return (inet_ntop6(src, dst, size)); default: return TOOLKIT_EAFNOSUPPORT; } /* NOTREACHED */ } static int inet_ntop4(const unsigned char* src, char* dst, size_t size) { static const char fmt[] = "%u.%u.%u.%u"; char tmp[16]; int l; l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]); if (l <= 0 || (size_t)l >= size) { return TOOLKIT_ENOSPC; } strscpy(dst, tmp, size); return 0; } static int inet_ntop6(const unsigned char* src, char* dst, size_t size) { /* * Note that int32_t and int16_t need only be "at least" large enough * to contain a value of the specified size. On some systems, like * Crays, there is no such thing as an integer variable with 16 bits. * Keep this in mind if you think this function should have been coded * to use pointer overlays. All the world's not a VAX. */ char tmp[46], * tp; struct { int base, len; } best, cur; unsigned int words[sizeof(struct in6_addr) / sizeof(uint16_t)]; int i; /* * Preprocess: * Copy the input (bytewise) array into a wordwise array. * Find the longest run of 0x00's in src[] for :: shorthanding. */ memset(words, '\0', sizeof words); for (i = 0; i < (int)sizeof(struct in6_addr); i++) words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); best.base = -1; best.len = 0; cur.base = -1; cur.len = 0; for (i = 0; i < (int)array_size(words); i++) { if (words[i] == 0) { if (cur.base == -1) cur.base = i, cur.len = 1; else cur.len++; } else { if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; cur.base = -1; } } } if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; } if (best.base != -1 && best.len < 2) best.base = -1; /* * Format the result. */ tp = tmp; for (i = 0; i < (int)array_size(words); i++) { /* Are we inside the best run of 0x00's? */ if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { if (i == best.base) *tp++ = ':'; continue; } /* Are we following an initial run of 0x00s or any real hex? */ if (i != 0) *tp++ = ':'; /* Is this address an encapsulated IPv4? */ if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 7 && words[7] != 0x0001) || (best.len == 5 && words[5] == 0xffff))) { int err = inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)); if (err) return err; tp += strlen(tp); break; } tp += sprintf(tp, "%x", words[i]); } /* Was it a trailing run of 0x00's? */ if (best.base != -1 && (best.base + best.len) == array_size(words)) *tp++ = ':'; *tp++ = '\0'; if (TOOLKIT_E2BIG == strscpy(dst, tmp, size)) return TOOLKIT_ENOSPC; return 0; } #endif int toolkit_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) { return toolkit_inet_ntop(AF_INET, &src->sin_addr, dst, size); } int toolkit_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) { return toolkit_inet_ntop(AF_INET6, &src->sin6_addr, dst, size); } void toolkit_free_environ(toolkit_env_item_t* envitems, int count) { int i; for (i = 0; i < count; i++) { FREE(envitems[i].name); } FREE(envitems); } void toolkit_free_cpu_info(toolkit_cpu_info_t* cpu_infos, int count) { int i; for (i = 0; i < count; i++) { FREE(cpu_infos[i].model); } FREE(cpu_infos); } /** WARNING: need to FREE the copy msg!!!!*/ static const char* toolkit__unknown_err_code(int err) { char buf[32]; char* copy; snprintf(buf, sizeof(buf), "Unknown system error %d", err); copy = STRDUP(buf); return copy != NULL ? copy : "Unknown system error"; } #define TOOLKIT_STRERROR_GEN(name, msg) case TOOLKIT_ ## name: return msg; const char* toolkit_strerror(int err) { switch (err) { TOOLKIT_ERRNO_MAP(TOOLKIT_STRERROR_GEN) } return toolkit__unknown_err_code(err); } #undef TOOLKIT_STRERROR_GEN #define TOOLKIT_STRERROR_GEN_R(name, msg) \ case TOOLKIT_ ## name: \ snprintf(buf, buflen, "%s", msg); break; char* toolkit_strerror_r(int err, char* buf, size_t buflen) { switch (err) { TOOLKIT_ERRNO_MAP(TOOLKIT_STRERROR_GEN_R) default: snprintf(buf, buflen, "Unknown system error %d", err); } return buf; } #undef TOOLKIT_STRERROR_GEN_R #define TOOLKIT_ERR_NAME_GEN(name, _) case TOOLKIT_ ## name: return #name; const char* toolkit_err_name(int err) { switch (err) { TOOLKIT_ERRNO_MAP(TOOLKIT_ERR_NAME_GEN) } return toolkit__unknown_err_code(err); } #undef TOOLKIT_ERR_NAME_GEN #define TOOLKIT_ERR_NAME_GEN_R(name, _) \ case TOOLKIT_## name: \ snprintf(buf, buflen, "%s", #name); break; char* toolkit_err_name_r(int err, char* buf, size_t buflen) { switch (err) { TOOLKIT_ERRNO_MAP(TOOLKIT_ERR_NAME_GEN_R) default: snprintf(buf, buflen, "Unknown system error %d", err); } return buf; } #undef TOOLKIT_ERR_NAME_GEN_R