/* <string> getenv false */ static int zgetenv(i_ctx_t *i_ctx_p) { os_ptr op = osp; char *str; byte *value; int len = 0; check_read_type(*op, t_string); str = ref_to_string(op, imemory, "getenv key"); if (str == 0) return_error(e_VMerror); if (gp_getenv(str, (char *)0, &len) > 0) { /* key missing */ ifree_string((byte *) str, r_size(op) + 1, "getenv key"); make_false(op); return 0; } value = ialloc_string(len, "getenv value"); if (value == 0) { ifree_string((byte *) str, r_size(op) + 1, "getenv key"); return_error(e_VMerror); } DISCARD(gp_getenv(str, (char *)value, &len)); /* can't fail */ ifree_string((byte *) str, r_size(op) + 1, "getenv key"); /* Delete the stupid C string terminator. */ value = iresize_string(value, len, len - 1, "getenv value"); /* can't fail */ push(1); make_string(op - 1, a_all | icurrent_space, len - 1, value); make_true(op); return 0; }
/* Convert a string from the current locale's character set to UTF-8. * Unfortunately, "current locale" can mean a few different things on * Windows -- we use the default ANSI code page, which does the right * thing for command-line arguments (like "-sPDFPassword=foo") and * for strings typed as input to gswin32.exe. It doesn't work for * strings typed as input to gswin32c.exe, which are normally in the * default OEM code page instead. * <string> .locale_to_utf8 <string> */ static int zlocale_to_utf8(i_ctx_t *i_ctx_p) { #define LOCALE_TO_UTF8_BUFFER_SIZE 1024 os_ptr op = osp; char *input; WCHAR wide_buffer[LOCALE_TO_UTF8_BUFFER_SIZE]; char utf8_buffer[LOCALE_TO_UTF8_BUFFER_SIZE]; int success; int code; check_read_type(*op, t_string); input = ref_to_string(op, imemory, "locale_to_utf8 input"); if (input == 0) return_error(gs_error_VMerror); success = MultiByteToWideChar(CP_ACP, 0, input, -1, wide_buffer, LOCALE_TO_UTF8_BUFFER_SIZE); ifree_string((byte *)input, r_size(op) + 1, "locale_to_utf8 input"); if (success == 0) return_error(gs_error_ioerror); success = WideCharToMultiByte(CP_UTF8, 0, wide_buffer, -1, utf8_buffer, LOCALE_TO_UTF8_BUFFER_SIZE, NULL, NULL); if (success == 0) return_error(gs_error_ioerror); code = string_to_ref(utf8_buffer, op, iimemory, "locale_to_utf8 output"); if (code < 0) return code; return 0; #undef LOCALE_TO_UTF8_BUFFER_SIZE }
/* Convert a file name to a C string by adding a null terminator. */ int terminate_file_name(parsed_file_name *pfn, client_name_t cname) { uint len = pfn->len; ref fnref; const char *fname; if ( pfn->iodev == NULL ) /* no device */ pfn->iodev = iodev_default; fnref.value.const_bytes = (const byte *)pfn->fname; r_set_size(&fnref, len); fname = ref_to_string(&fnref, imemory, cname); if ( fname == 0 ) return_error(e_VMerror); pfn->fname = fname; pfn->len = len + 1; /* null terminator */ return 0; }
/* Convert a string from the current locale's character set to UTF-8. * <string> .locale_to_utf8 <string> */ static int zlocale_to_utf8(i_ctx_t *i_ctx_p) { os_ptr op = osp; char *input; char *output; int code; check_read_type(*op, t_string); input = ref_to_string(op, imemory, "locale_to_utf8 input"); if (input == 0) return_error(gs_error_VMerror); output = stringprep_locale_to_utf8(input); ifree_string((byte *)input, r_size(op) + 1, "locale_to_utf8 input"); if (output == 0) { /* This function is intended to be used on strings whose * character set is unknown, so it's not an error if the * input contains invalid characters. Just return the input * string unchanged. * * Sadly, EINVAL from stringprep_locale_to_utf8 can mean * either an invalid character set conversion (which we care * about), or an incomplete input string (which we don't). * For now, we ignore EINVAL; the right solution is probably * to not use stringprep_locale_to_utf8, and just call iconv * by hand. */ if (errno == EILSEQ || errno == EINVAL) return 0; /* Other errors (like ENFILE) are real errors, which we * want to return to the user. */ return_error(gs_error_ioerror); } code = string_to_ref(output, op, iimemory, "locale_to_utf8 output"); free(output); if (code < 0) return code; return 0; }