1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 2004 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at http://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 23#include "setup.h" 24 25#ifdef HAVE_STRERROR_R 26# if (!defined(HAVE_POSIX_STRERROR_R) && \ 27 !defined(HAVE_GLIBC_STRERROR_R) && \ 28 !defined(HAVE_VXWORKS_STRERROR_R)) || \ 29 (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \ 30 (defined(HAVE_GLIBC_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \ 31 (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)) 32# error "strerror_r MUST be either POSIX, glibc or vxworks-style" 33# endif 34#endif 35 36#include <curl/curl.h> 37 38#ifdef USE_LIBIDN 39#include <idna.h> 40#endif 41 42#include "strerror.h" 43 44#define _MPRINTF_REPLACE /* use our functions only */ 45#include <curl/mprintf.h> 46 47 48const char * 49curl_easy_strerror(CURLcode error) 50{ 51#ifndef CURL_DISABLE_VERBOSE_STRINGS 52 switch (error) { 53 case CURLE_OK: 54 return "No error"; 55 56 case CURLE_UNSUPPORTED_PROTOCOL: 57 return "Unsupported protocol"; 58 59 case CURLE_FAILED_INIT: 60 return "Failed initialization"; 61 62 case CURLE_URL_MALFORMAT: 63 return "URL using bad/illegal format or missing URL"; 64 65 case CURLE_NOT_BUILT_IN: 66 return "A requested feature, protocol or option was not found built-in in" 67 " this libcurl due to a build-time decision."; 68 69 case CURLE_COULDNT_RESOLVE_PROXY: 70 return "Couldn't resolve proxy name"; 71 72 case CURLE_COULDNT_RESOLVE_HOST: 73 return "Couldn't resolve host name"; 74 75 case CURLE_COULDNT_CONNECT: 76 return "Couldn't connect to server"; 77 78 case CURLE_FTP_WEIRD_SERVER_REPLY: 79 return "FTP: weird server reply"; 80 81 case CURLE_REMOTE_ACCESS_DENIED: 82 return "Access denied to remote resource"; 83 84 case CURLE_FTP_PRET_FAILED: 85 return "FTP: The server did not accept the PRET command."; 86 87 case CURLE_FTP_WEIRD_PASS_REPLY: 88 return "FTP: unknown PASS reply"; 89 90 case CURLE_FTP_WEIRD_PASV_REPLY: 91 return "FTP: unknown PASV reply"; 92 93 case CURLE_FTP_WEIRD_227_FORMAT: 94 return "FTP: unknown 227 response format"; 95 96 case CURLE_FTP_CANT_GET_HOST: 97 return "FTP: can't figure out the host in the PASV response"; 98 99 case CURLE_FTP_COULDNT_SET_TYPE: 100 return "FTP: couldn't set file type"; 101 102 case CURLE_PARTIAL_FILE: 103 return "Transferred a partial file"; 104 105 case CURLE_FTP_COULDNT_RETR_FILE: 106 return "FTP: couldn't retrieve (RETR failed) the specified file"; 107 108 case CURLE_QUOTE_ERROR: 109 return "Quote command returned error"; 110 111 case CURLE_HTTP_RETURNED_ERROR: 112 return "HTTP response code said error"; 113 114 case CURLE_WRITE_ERROR: 115 return "Failed writing received data to disk/application"; 116 117 case CURLE_UPLOAD_FAILED: 118 return "Upload failed (at start/before it took off)"; 119 120 case CURLE_READ_ERROR: 121 return "Failed to open/read local data from file/application"; 122 123 case CURLE_OUT_OF_MEMORY: 124 return "Out of memory"; 125 126 case CURLE_OPERATION_TIMEDOUT: 127 return "Timeout was reached"; 128 129 case CURLE_FTP_PORT_FAILED: 130 return "FTP: command PORT failed"; 131 132 case CURLE_FTP_COULDNT_USE_REST: 133 return "FTP: command REST failed"; 134 135 case CURLE_RANGE_ERROR: 136 return "Requested range was not delivered by the server"; 137 138 case CURLE_HTTP_POST_ERROR: 139 return "Internal problem setting up the POST"; 140 141 case CURLE_SSL_CONNECT_ERROR: 142 return "SSL connect error"; 143 144 case CURLE_BAD_DOWNLOAD_RESUME: 145 return "Couldn't resume download"; 146 147 case CURLE_FILE_COULDNT_READ_FILE: 148 return "Couldn't read a file:// file"; 149 150 case CURLE_LDAP_CANNOT_BIND: 151 return "LDAP: cannot bind"; 152 153 case CURLE_LDAP_SEARCH_FAILED: 154 return "LDAP: search failed"; 155 156 case CURLE_FUNCTION_NOT_FOUND: 157 return "A required function in the library was not found"; 158 159 case CURLE_ABORTED_BY_CALLBACK: 160 return "Operation was aborted by an application callback"; 161 162 case CURLE_BAD_FUNCTION_ARGUMENT: 163 return "A libcurl function was given a bad argument"; 164 165 case CURLE_INTERFACE_FAILED: 166 return "Failed binding local connection end"; 167 168 case CURLE_TOO_MANY_REDIRECTS : 169 return "Number of redirects hit maximum amount"; 170 171 case CURLE_UNKNOWN_OPTION: 172 return "An unknown option was passed in to libcurl"; 173 174 case CURLE_TELNET_OPTION_SYNTAX : 175 return "Malformed telnet option"; 176 177 case CURLE_PEER_FAILED_VERIFICATION: 178 return "SSL peer certificate or SSH remote key was not OK"; 179 180 case CURLE_GOT_NOTHING: 181 return "Server returned nothing (no headers, no data)"; 182 183 case CURLE_SSL_ENGINE_NOTFOUND: 184 return "SSL crypto engine not found"; 185 186 case CURLE_SSL_ENGINE_SETFAILED: 187 return "Can not set SSL crypto engine as default"; 188 189 case CURLE_SSL_ENGINE_INITFAILED: 190 return "Failed to initialise SSL crypto engine"; 191 192 case CURLE_SEND_ERROR: 193 return "Failed sending data to the peer"; 194 195 case CURLE_RECV_ERROR: 196 return "Failure when receiving data from the peer"; 197 198 case CURLE_SSL_CERTPROBLEM: 199 return "Problem with the local SSL certificate"; 200 201 case CURLE_SSL_CIPHER: 202 return "Couldn't use specified SSL cipher"; 203 204 case CURLE_SSL_CACERT: 205 return "Peer certificate cannot be authenticated with given CA " 206 "certificates"; 207 208 case CURLE_SSL_CACERT_BADFILE: 209 return "Problem with the SSL CA cert (path? access rights?)"; 210 211 case CURLE_BAD_CONTENT_ENCODING: 212 return "Unrecognized or bad HTTP Content or Transfer-Encoding"; 213 214 case CURLE_LDAP_INVALID_URL: 215 return "Invalid LDAP URL"; 216 217 case CURLE_FILESIZE_EXCEEDED: 218 return "Maximum file size exceeded"; 219 220 case CURLE_USE_SSL_FAILED: 221 return "Requested SSL level failed"; 222 223 case CURLE_SSL_SHUTDOWN_FAILED: 224 return "Failed to shut down the SSL connection"; 225 226 case CURLE_SSL_CRL_BADFILE: 227 return "Failed to load CRL file (path? access rights?, format?)"; 228 229 case CURLE_SSL_ISSUER_ERROR: 230 return "Issuer check against peer certificate failed"; 231 232 case CURLE_SEND_FAIL_REWIND: 233 return "Send failed since rewinding of the data stream failed"; 234 235 case CURLE_LOGIN_DENIED: 236 return "Login denied"; 237 238 case CURLE_TFTP_NOTFOUND: 239 return "TFTP: File Not Found"; 240 241 case CURLE_TFTP_PERM: 242 return "TFTP: Access Violation"; 243 244 case CURLE_REMOTE_DISK_FULL: 245 return "Disk full or allocation exceeded"; 246 247 case CURLE_TFTP_ILLEGAL: 248 return "TFTP: Illegal operation"; 249 250 case CURLE_TFTP_UNKNOWNID: 251 return "TFTP: Unknown transfer ID"; 252 253 case CURLE_REMOTE_FILE_EXISTS: 254 return "Remote file already exists"; 255 256 case CURLE_TFTP_NOSUCHUSER: 257 return "TFTP: No such user"; 258 259 case CURLE_CONV_FAILED: 260 return "Conversion failed"; 261 262 case CURLE_CONV_REQD: 263 return "Caller must register CURLOPT_CONV_ callback options"; 264 265 case CURLE_REMOTE_FILE_NOT_FOUND: 266 return "Remote file not found"; 267 268 case CURLE_SSH: 269 return "Error in the SSH layer"; 270 271 case CURLE_AGAIN: 272 return "Socket not ready for send/recv"; 273 274 case CURLE_RTSP_CSEQ_ERROR: 275 return "RTSP CSeq mismatch or invalid CSeq"; 276 277 case CURLE_RTSP_SESSION_ERROR: 278 return "RTSP session error"; 279 280 case CURLE_FTP_BAD_FILE_LIST: 281 return "Unable to parse FTP file list"; 282 283 case CURLE_CHUNK_FAILED: 284 return "Chunk callback failed"; 285 286 /* error codes not used by current libcurl */ 287 case CURLE_OBSOLETE10: 288 case CURLE_OBSOLETE12: 289 case CURLE_OBSOLETE16: 290 case CURLE_OBSOLETE20: 291 case CURLE_OBSOLETE24: 292 case CURLE_OBSOLETE29: 293 case CURLE_OBSOLETE32: 294 case CURLE_OBSOLETE40: 295 case CURLE_OBSOLETE44: 296 case CURLE_OBSOLETE46: 297 case CURLE_OBSOLETE50: 298 case CURLE_OBSOLETE57: 299 case CURL_LAST: 300 break; 301 } 302 /* 303 * By using a switch, gcc -Wall will complain about enum values 304 * which do not appear, helping keep this function up-to-date. 305 * By using gcc -Wall -Werror, you can't forget. 306 * 307 * A table would not have the same benefit. Most compilers will 308 * generate code very similar to a table in any case, so there 309 * is little performance gain from a table. And something is broken 310 * for the user's application, anyways, so does it matter how fast 311 * it _doesn't_ work? 312 * 313 * The line number for the error will be near this comment, which 314 * is why it is here, and not at the start of the switch. 315 */ 316 return "Unknown error"; 317#else 318 if(error == CURLE_OK) 319 return "No error"; 320 else 321 return "Error"; 322#endif 323} 324 325const char * 326curl_multi_strerror(CURLMcode error) 327{ 328#ifndef CURL_DISABLE_VERBOSE_STRINGS 329 switch (error) { 330 case CURLM_CALL_MULTI_PERFORM: 331 return "Please call curl_multi_perform() soon"; 332 333 case CURLM_OK: 334 return "No error"; 335 336 case CURLM_BAD_HANDLE: 337 return "Invalid multi handle"; 338 339 case CURLM_BAD_EASY_HANDLE: 340 return "Invalid easy handle"; 341 342 case CURLM_OUT_OF_MEMORY: 343 return "Out of memory"; 344 345 case CURLM_INTERNAL_ERROR: 346 return "Internal error"; 347 348 case CURLM_BAD_SOCKET: 349 return "Invalid socket argument"; 350 351 case CURLM_UNKNOWN_OPTION: 352 return "Unknown option"; 353 354 case CURLM_LAST: 355 break; 356 } 357 358 return "Unknown error"; 359#else 360 if(error == CURLM_OK) 361 return "No error"; 362 else 363 return "Error"; 364#endif 365} 366 367const char * 368curl_share_strerror(CURLSHcode error) 369{ 370#ifndef CURL_DISABLE_VERBOSE_STRINGS 371 switch (error) { 372 case CURLSHE_OK: 373 return "No error"; 374 375 case CURLSHE_BAD_OPTION: 376 return "Unknown share option"; 377 378 case CURLSHE_IN_USE: 379 return "Share currently in use"; 380 381 case CURLSHE_INVALID: 382 return "Invalid share handle"; 383 384 case CURLSHE_NOMEM: 385 return "Out of memory"; 386 387 case CURLSHE_NOT_BUILT_IN: 388 return "Feature not enabled in this library"; 389 390 case CURLSHE_LAST: 391 break; 392 } 393 394 return "CURLSHcode unknown"; 395#else 396 if(error == CURLSHE_OK) 397 return "No error"; 398 else 399 return "Error"; 400#endif 401} 402 403#ifdef USE_WINSOCK 404 405/* This function handles most / all (?) Winsock errors cURL is able to produce. 406 */ 407static const char * 408get_winsock_error (int err, char *buf, size_t len) 409{ 410 const char *p; 411 412#ifndef CURL_DISABLE_VERBOSE_STRINGS 413 switch (err) { 414 case WSAEINTR: 415 p = "Call interrupted"; 416 break; 417 case WSAEBADF: 418 p = "Bad file"; 419 break; 420 case WSAEACCES: 421 p = "Bad access"; 422 break; 423 case WSAEFAULT: 424 p = "Bad argument"; 425 break; 426 case WSAEINVAL: 427 p = "Invalid arguments"; 428 break; 429 case WSAEMFILE: 430 p = "Out of file descriptors"; 431 break; 432 case WSAEWOULDBLOCK: 433 p = "Call would block"; 434 break; 435 case WSAEINPROGRESS: 436 case WSAEALREADY: 437 p = "Blocking call in progress"; 438 break; 439 case WSAENOTSOCK: 440 p = "Descriptor is not a socket"; 441 break; 442 case WSAEDESTADDRREQ: 443 p = "Need destination address"; 444 break; 445 case WSAEMSGSIZE: 446 p = "Bad message size"; 447 break; 448 case WSAEPROTOTYPE: 449 p = "Bad protocol"; 450 break; 451 case WSAENOPROTOOPT: 452 p = "Protocol option is unsupported"; 453 break; 454 case WSAEPROTONOSUPPORT: 455 p = "Protocol is unsupported"; 456 break; 457 case WSAESOCKTNOSUPPORT: 458 p = "Socket is unsupported"; 459 break; 460 case WSAEOPNOTSUPP: 461 p = "Operation not supported"; 462 break; 463 case WSAEAFNOSUPPORT: 464 p = "Address family not supported"; 465 break; 466 case WSAEPFNOSUPPORT: 467 p = "Protocol family not supported"; 468 break; 469 case WSAEADDRINUSE: 470 p = "Address already in use"; 471 break; 472 case WSAEADDRNOTAVAIL: 473 p = "Address not available"; 474 break; 475 case WSAENETDOWN: 476 p = "Network down"; 477 break; 478 case WSAENETUNREACH: 479 p = "Network unreachable"; 480 break; 481 case WSAENETRESET: 482 p = "Network has been reset"; 483 break; 484 case WSAECONNABORTED: 485 p = "Connection was aborted"; 486 break; 487 case WSAECONNRESET: 488 p = "Connection was reset"; 489 break; 490 case WSAENOBUFS: 491 p = "No buffer space"; 492 break; 493 case WSAEISCONN: 494 p = "Socket is already connected"; 495 break; 496 case WSAENOTCONN: 497 p = "Socket is not connected"; 498 break; 499 case WSAESHUTDOWN: 500 p = "Socket has been shut down"; 501 break; 502 case WSAETOOMANYREFS: 503 p = "Too many references"; 504 break; 505 case WSAETIMEDOUT: 506 p = "Timed out"; 507 break; 508 case WSAECONNREFUSED: 509 p = "Connection refused"; 510 break; 511 case WSAELOOP: 512 p = "Loop??"; 513 break; 514 case WSAENAMETOOLONG: 515 p = "Name too long"; 516 break; 517 case WSAEHOSTDOWN: 518 p = "Host down"; 519 break; 520 case WSAEHOSTUNREACH: 521 p = "Host unreachable"; 522 break; 523 case WSAENOTEMPTY: 524 p = "Not empty"; 525 break; 526 case WSAEPROCLIM: 527 p = "Process limit reached"; 528 break; 529 case WSAEUSERS: 530 p = "Too many users"; 531 break; 532 case WSAEDQUOT: 533 p = "Bad quota"; 534 break; 535 case WSAESTALE: 536 p = "Something is stale"; 537 break; 538 case WSAEREMOTE: 539 p = "Remote error"; 540 break; 541#ifdef WSAEDISCON /* missing in SalfordC! */ 542 case WSAEDISCON: 543 p = "Disconnected"; 544 break; 545#endif 546 /* Extended Winsock errors */ 547 case WSASYSNOTREADY: 548 p = "Winsock library is not ready"; 549 break; 550 case WSANOTINITIALISED: 551 p = "Winsock library not initialised"; 552 break; 553 case WSAVERNOTSUPPORTED: 554 p = "Winsock version not supported"; 555 break; 556 557 /* getXbyY() errors (already handled in herrmsg): 558 * Authoritative Answer: Host not found */ 559 case WSAHOST_NOT_FOUND: 560 p = "Host not found"; 561 break; 562 563 /* Non-Authoritative: Host not found, or SERVERFAIL */ 564 case WSATRY_AGAIN: 565 p = "Host not found, try again"; 566 break; 567 568 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ 569 case WSANO_RECOVERY: 570 p = "Unrecoverable error in call to nameserver"; 571 break; 572 573 /* Valid name, no data record of requested type */ 574 case WSANO_DATA: 575 p = "No data record of requested type"; 576 break; 577 578 default: 579 return NULL; 580 } 581#else 582 if(err == CURLE_OK) 583 return NULL; 584 else 585 p = "error"; 586#endif 587 strncpy (buf, p, len); 588 buf [len-1] = '\0'; 589 return buf; 590} 591#endif /* USE_WINSOCK */ 592 593/* 594 * Our thread-safe and smart strerror() replacement. 595 * 596 * The 'err' argument passed in to this function MUST be a true errno number 597 * as reported on this system. We do no range checking on the number before 598 * we pass it to the "number-to-message" conversion function and there might 599 * be systems that don't do proper range checking in there themselves. 600 * 601 * We don't do range checking (on systems other than Windows) since there is 602 * no good reliable and portable way to do it. 603 */ 604const char *Curl_strerror(struct connectdata *conn, int err) 605{ 606 char *buf, *p; 607 size_t max; 608 int old_errno = ERRNO; 609 610 DEBUGASSERT(conn); 611 DEBUGASSERT(err >= 0); 612 613 buf = conn->syserr_buf; 614 max = sizeof(conn->syserr_buf)-1; 615 *buf = '\0'; 616 617#ifdef USE_WINSOCK 618 619#ifdef _WIN32_WCE 620 { 621 wchar_t wbuf[256]; 622 wbuf[0] = L'\0'; 623 624 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 625 LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL); 626 wcstombs(buf,wbuf,max); 627 } 628#else 629 /* 'sys_nerr' is the maximum errno number, it is not widely portable */ 630 if(err >= 0 && err < sys_nerr) 631 strncpy(buf, strerror(err), max); 632 else { 633 if(!get_winsock_error(err, buf, max) && 634 !FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 635 LANG_NEUTRAL, buf, (DWORD)max, NULL)) 636 snprintf(buf, max, "Unknown error %d (%#x)", err, err); 637 } 638#endif 639 640#else /* not USE_WINSOCK coming up */ 641 642#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R) 643 /* 644 * The POSIX-style strerror_r() may set errno to ERANGE if insufficient 645 * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated 646 * message string, or EINVAL if 'errnum' is not a valid error number. 647 */ 648 if(0 != strerror_r(err, buf, max)) { 649 if('\0' == buf[0]) 650 snprintf(buf, max, "Unknown error %d", err); 651 } 652#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R) 653 /* 654 * The glibc-style strerror_r() only *might* use the buffer we pass to 655 * the function, but it always returns the error message as a pointer, 656 * so we must copy that string unconditionally (if non-NULL). 657 */ 658 { 659 char buffer[256]; 660 char *msg = strerror_r(err, buffer, sizeof(buffer)); 661 if(msg) 662 strncpy(buf, msg, max); 663 else 664 snprintf(buf, max, "Unknown error %d", err); 665 } 666#elif defined(HAVE_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R) 667 /* 668 * The vxworks-style strerror_r() does use the buffer we pass to the function. 669 * The buffer size should be at least MAXERRSTR_SIZE (150) defined in rtsold.h 670 */ 671 { 672 char buffer[256]; 673 if(OK == strerror_r(err, buffer)) 674 strncpy(buf, buffer, max); 675 else 676 snprintf(buf, max, "Unknown error %d", err); 677 } 678#else 679 { 680 char *msg = strerror(err); 681 if(msg) 682 strncpy(buf, msg, max); 683 else 684 snprintf(buf, max, "Unknown error %d", err); 685 } 686#endif 687 688#endif /* end of ! USE_WINSOCK */ 689 690 buf[max] = '\0'; /* make sure the string is zero terminated */ 691 692 /* strip trailing '\r\n' or '\n'. */ 693 if((p = strrchr(buf,'\n')) != NULL && (p - buf) >= 2) 694 *p = '\0'; 695 if((p = strrchr(buf,'\r')) != NULL && (p - buf) >= 1) 696 *p = '\0'; 697 698 if(old_errno != ERRNO) 699 SET_ERRNO(old_errno); 700 701 return buf; 702} 703 704#ifdef USE_LIBIDN 705/* 706 * Return error-string for libidn status as returned from idna_to_ascii_lz(). 707 */ 708const char *Curl_idn_strerror (struct connectdata *conn, int err) 709{ 710#ifdef HAVE_IDNA_STRERROR 711 (void)conn; 712 return idna_strerror((Idna_rc) err); 713#else 714 const char *str; 715 char *buf; 716 size_t max; 717 718 DEBUGASSERT(conn); 719 720 buf = conn->syserr_buf; 721 max = sizeof(conn->syserr_buf)-1; 722 *buf = '\0'; 723 724#ifndef CURL_DISABLE_VERBOSE_STRINGS 725 switch ((Idna_rc)err) { 726 case IDNA_SUCCESS: 727 str = "No error"; 728 break; 729 case IDNA_STRINGPREP_ERROR: 730 str = "Error in string preparation"; 731 break; 732 case IDNA_PUNYCODE_ERROR: 733 str = "Error in Punycode operation"; 734 break; 735 case IDNA_CONTAINS_NON_LDH: 736 str = "Illegal ASCII characters"; 737 break; 738 case IDNA_CONTAINS_MINUS: 739 str = "Contains minus"; 740 break; 741 case IDNA_INVALID_LENGTH: 742 str = "Invalid output length"; 743 break; 744 case IDNA_NO_ACE_PREFIX: 745 str = "No ACE prefix (\"xn--\")"; 746 break; 747 case IDNA_ROUNDTRIP_VERIFY_ERROR: 748 str = "Round trip verify error"; 749 break; 750 case IDNA_CONTAINS_ACE_PREFIX: 751 str = "Already have ACE prefix (\"xn--\")"; 752 break; 753 case IDNA_ICONV_ERROR: 754 str = "Locale conversion failed"; 755 break; 756 case IDNA_MALLOC_ERROR: 757 str = "Allocation failed"; 758 break; 759 case IDNA_DLOPEN_ERROR: 760 str = "dlopen() error"; 761 break; 762 default: 763 snprintf(buf, max, "error %d", err); 764 str = NULL; 765 break; 766 } 767#else 768 if((Idna_rc)err == IDNA_SUCCESS) 769 str = "No error"; 770 else 771 str = "Error"; 772#endif 773 if(str) 774 strncpy(buf, str, max); 775 buf[max] = '\0'; 776 return (buf); 777#endif 778} 779#endif /* USE_LIBIDN */ 780