1 /* 2 * Localized printf/puts functions for CUPS. 3 * 4 * Copyright 2007-2014 by Apple Inc. 5 * Copyright 2002-2007 by Easy Software Products. 6 * 7 * These coded instructions, statements, and computer programs are the 8 * property of Apple Inc. and are protected by Federal copyright 9 * law. Distribution and use rights are outlined in the file "LICENSE.txt" 10 * which should have been included with this file. If this file is 11 * missing or damaged, see the license at "http://www.cups.org/". 12 * 13 * This file is subject to the Apple OS-Developed Software exception. 14 */ 15 16 /* 17 * Include necessary headers... 18 */ 19 20 #include "cups-private.h" 21 22 23 /* 24 * '_cupsLangPrintError()' - Print a message followed by a standard error. 25 */ 26 27 void 28 _cupsLangPrintError(const char *prefix, /* I - Non-localized message prefix */ 29 const char *message)/* I - Message */ 30 { 31 ssize_t bytes; /* Number of bytes formatted */ 32 int last_errno; /* Last error */ 33 char buffer[2048], /* Message buffer */ 34 *bufptr, /* Pointer into buffer */ 35 output[8192]; /* Output buffer */ 36 _cups_globals_t *cg; /* Global data */ 37 38 39 /* 40 * Range check... 41 */ 42 43 if (!message) 44 return; 45 46 /* 47 * Save the errno value... 48 */ 49 50 last_errno = errno; 51 52 /* 53 * Get the message catalog... 54 */ 55 56 cg = _cupsGlobals(); 57 58 if (!cg->lang_default) 59 cg->lang_default = cupsLangDefault(); 60 61 /* 62 * Format the message... 63 */ 64 65 if (prefix) 66 { 67 snprintf(buffer, sizeof(buffer), "%s:", prefix); 68 bufptr = buffer + strlen(buffer); 69 } 70 else 71 bufptr = buffer; 72 73 snprintf(bufptr, sizeof(buffer) - (size_t)(bufptr - buffer), 74 /* TRANSLATORS: Message is "subject: error" */ 75 _cupsLangString(cg->lang_default, _("%s: %s")), 76 _cupsLangString(cg->lang_default, message), strerror(last_errno)); 77 strlcat(buffer, "\n", sizeof(buffer)); 78 79 /* 80 * Convert and write to stderr... 81 */ 82 83 bytes = cupsUTF8ToCharset(output, (cups_utf8_t *)buffer, sizeof(output), 84 cg->lang_default->encoding); 85 86 if (bytes > 0) 87 fwrite(output, 1, (size_t)bytes, stderr); 88 } 89 90 91 /* 92 * '_cupsLangPrintFilter()' - Print a formatted filter message string to a file. 93 */ 94 95 int /* O - Number of bytes written */ 96 _cupsLangPrintFilter( 97 FILE *fp, /* I - File to write to */ 98 const char *prefix, /* I - Non-localized message prefix */ 99 const char *message, /* I - Message string to use */ 100 ...) /* I - Additional arguments as needed */ 101 { 102 ssize_t bytes; /* Number of bytes formatted */ 103 char temp[2048], /* Temporary format buffer */ 104 buffer[2048], /* Message buffer */ 105 output[8192]; /* Output buffer */ 106 va_list ap; /* Pointer to additional arguments */ 107 _cups_globals_t *cg; /* Global data */ 108 109 110 /* 111 * Range check... 112 */ 113 114 if (!fp || !message) 115 return (-1); 116 117 cg = _cupsGlobals(); 118 119 if (!cg->lang_default) 120 cg->lang_default = cupsLangDefault(); 121 122 /* 123 * Format the string... 124 */ 125 126 va_start(ap, message); 127 snprintf(temp, sizeof(temp), "%s: %s\n", prefix, 128 _cupsLangString(cg->lang_default, message)); 129 vsnprintf(buffer, sizeof(buffer), temp, ap); 130 va_end(ap); 131 132 /* 133 * Transcode to the destination charset... 134 */ 135 136 bytes = cupsUTF8ToCharset(output, (cups_utf8_t *)buffer, sizeof(output), 137 cg->lang_default->encoding); 138 139 /* 140 * Write the string and return the number of bytes written... 141 */ 142 143 if (bytes > 0) 144 return ((int)fwrite(output, 1, (size_t)bytes, fp)); 145 else 146 return ((int)bytes); 147 } 148 149 150 /* 151 * '_cupsLangPrintf()' - Print a formatted message string to a file. 152 */ 153 154 int /* O - Number of bytes written */ 155 _cupsLangPrintf(FILE *fp, /* I - File to write to */ 156 const char *message, /* I - Message string to use */ 157 ...) /* I - Additional arguments as needed */ 158 { 159 ssize_t bytes; /* Number of bytes formatted */ 160 char buffer[2048], /* Message buffer */ 161 output[8192]; /* Output buffer */ 162 va_list ap; /* Pointer to additional arguments */ 163 _cups_globals_t *cg; /* Global data */ 164 165 166 /* 167 * Range check... 168 */ 169 170 if (!fp || !message) 171 return (-1); 172 173 cg = _cupsGlobals(); 174 175 if (!cg->lang_default) 176 cg->lang_default = cupsLangDefault(); 177 178 /* 179 * Format the string... 180 */ 181 182 va_start(ap, message); 183 vsnprintf(buffer, sizeof(buffer) - 1, 184 _cupsLangString(cg->lang_default, message), ap); 185 va_end(ap); 186 187 strlcat(buffer, "\n", sizeof(buffer)); 188 189 /* 190 * Transcode to the destination charset... 191 */ 192 193 bytes = cupsUTF8ToCharset(output, (cups_utf8_t *)buffer, sizeof(output), 194 cg->lang_default->encoding); 195 196 /* 197 * Write the string and return the number of bytes written... 198 */ 199 200 if (bytes > 0) 201 return ((int)fwrite(output, 1, (size_t)bytes, fp)); 202 else 203 return ((int)bytes); 204 } 205 206 207 /* 208 * '_cupsLangPuts()' - Print a static message string to a file. 209 */ 210 211 int /* O - Number of bytes written */ 212 _cupsLangPuts(FILE *fp, /* I - File to write to */ 213 const char *message) /* I - Message string to use */ 214 { 215 ssize_t bytes; /* Number of bytes formatted */ 216 char output[8192]; /* Message buffer */ 217 _cups_globals_t *cg; /* Global data */ 218 219 220 /* 221 * Range check... 222 */ 223 224 if (!fp || !message) 225 return (-1); 226 227 cg = _cupsGlobals(); 228 229 if (!cg->lang_default) 230 cg->lang_default = cupsLangDefault(); 231 232 /* 233 * Transcode to the destination charset... 234 */ 235 236 bytes = cupsUTF8ToCharset(output, 237 (cups_utf8_t *)_cupsLangString(cg->lang_default, 238 message), 239 sizeof(output) - 4, cg->lang_default->encoding); 240 bytes += cupsUTF8ToCharset(output + bytes, (cups_utf8_t *)"\n", (int)(sizeof(output) - (size_t)bytes), cg->lang_default->encoding); 241 242 /* 243 * Write the string and return the number of bytes written... 244 */ 245 246 if (bytes > 0) 247 return ((int)fwrite(output, 1, (size_t)bytes, fp)); 248 else 249 return ((int)bytes); 250 } 251 252 253 /* 254 * '_cupsSetLocale()' - Set the current locale and transcode the command-line. 255 */ 256 257 void 258 _cupsSetLocale(char *argv[]) /* IO - Command-line arguments */ 259 { 260 int i; /* Looping var */ 261 char buffer[8192]; /* Command-line argument buffer */ 262 _cups_globals_t *cg; /* Global data */ 263 #ifdef LC_TIME 264 const char *lc_time; /* Current LC_TIME value */ 265 char new_lc_time[255], /* New LC_TIME value */ 266 *charset; /* Pointer to character set */ 267 #endif /* LC_TIME */ 268 269 270 /* 271 * Set the locale so that times, etc. are displayed properly. 272 * 273 * Unfortunately, while we need the localized time value, we *don't* 274 * want to use the localized charset for the time value, so we need 275 * to set LC_TIME to the locale name with .UTF-8 on the end (if 276 * the locale includes a character set specifier...) 277 */ 278 279 setlocale(LC_ALL, ""); 280 281 #ifdef LC_TIME 282 if ((lc_time = setlocale(LC_TIME, NULL)) == NULL) 283 lc_time = setlocale(LC_ALL, NULL); 284 285 if (lc_time) 286 { 287 strlcpy(new_lc_time, lc_time, sizeof(new_lc_time)); 288 if ((charset = strchr(new_lc_time, '.')) == NULL) 289 charset = new_lc_time + strlen(new_lc_time); 290 291 strlcpy(charset, ".UTF-8", sizeof(new_lc_time) - (size_t)(charset - new_lc_time)); 292 } 293 else 294 strlcpy(new_lc_time, "C", sizeof(new_lc_time)); 295 296 setlocale(LC_TIME, new_lc_time); 297 #endif /* LC_TIME */ 298 299 /* 300 * Initialize the default language info... 301 */ 302 303 cg = _cupsGlobals(); 304 305 if (!cg->lang_default) 306 cg->lang_default = cupsLangDefault(); 307 308 /* 309 * Transcode the command-line arguments from the locale charset to 310 * UTF-8... 311 */ 312 313 if (cg->lang_default->encoding != CUPS_US_ASCII && 314 cg->lang_default->encoding != CUPS_UTF8) 315 { 316 for (i = 1; argv[i]; i ++) 317 { 318 /* 319 * Try converting from the locale charset to UTF-8... 320 */ 321 322 if (cupsCharsetToUTF8((cups_utf8_t *)buffer, argv[i], sizeof(buffer), 323 cg->lang_default->encoding) < 0) 324 continue; 325 326 /* 327 * Save the new string if it differs from the original... 328 */ 329 330 if (strcmp(buffer, argv[i])) 331 argv[i] = strdup(buffer); 332 } 333 } 334 } 335