os400sys.c (23348B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 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 https://curl.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 * SPDX-License-Identifier: curl 22 * 23 * 24 ***************************************************************************/ 25 26 /* OS/400 additional support. */ 27 28 #include <curl/curl.h> 29 #include "config-os400.h" /* Not curl_setup.h: we only need some defines. */ 30 31 #include <sys/types.h> 32 #include <sys/socket.h> 33 #include <sys/un.h> 34 35 #include <stdlib.h> 36 #include <stddef.h> 37 #include <string.h> 38 #include <pthread.h> 39 #include <netdb.h> 40 #include <qadrt.h> 41 #include <errno.h> 42 43 #ifdef HAVE_LIBZ 44 #include <zlib.h> 45 #endif 46 47 #ifdef HAVE_GSSAPI 48 #include <gssapi.h> 49 #endif 50 51 #ifndef CURL_DISABLE_LDAP 52 #include <ldap.h> 53 #endif 54 55 #include <netinet/in.h> 56 #include <arpa/inet.h> 57 58 #include "os400sys.h" 59 60 /** 61 *** QADRT OS/400 ASCII runtime defines only the most used procedures, but a 62 *** lot of them are not supported. This module implements ASCII wrappers for 63 *** those that are used by libcurl, but not defined by QADRT. 64 **/ 65 66 #pragma convert(0) /* Restore EBCDIC. */ 67 68 #define MIN_BYTE_GAIN 1024 /* Minimum gain when shortening a buffer. */ 69 70 struct buffer_t { 71 unsigned long size; /* Buffer size. */ 72 char *buf; /* Buffer address. */ 73 }; 74 75 76 static char *buffer_undef(localkey_t key, long size); 77 static char *buffer_threaded(localkey_t key, long size); 78 static char *buffer_unthreaded(localkey_t key, long size); 79 80 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 81 static pthread_key_t thdkey; 82 static struct buffer_t *locbufs; 83 84 char *(*Curl_thread_buffer)(localkey_t key, long size) = buffer_undef; 85 86 static void thdbufdestroy(void *private) 87 { 88 if(private) { 89 struct buffer_t *p = (struct buffer_t *) private; 90 localkey_t i; 91 92 for(i = (localkey_t) 0; i < LK_LAST; i++) { 93 free(p->buf); 94 p++; 95 } 96 97 free(private); 98 } 99 } 100 101 102 static void 103 terminate(void) 104 { 105 if(Curl_thread_buffer == buffer_threaded) { 106 locbufs = pthread_getspecific(thdkey); 107 pthread_setspecific(thdkey, (void *) NULL); 108 pthread_key_delete(thdkey); 109 } 110 111 if(Curl_thread_buffer != buffer_undef) { 112 thdbufdestroy((void *) locbufs); 113 locbufs = (struct buffer_t *) NULL; 114 } 115 116 Curl_thread_buffer = buffer_undef; 117 } 118 119 120 static char * 121 get_buffer(struct buffer_t *buf, long size) 122 { 123 char *cp; 124 125 /* If `size' >= 0, make sure buffer at `buf' is at least `size'-byte long. 126 Return the buffer address. */ 127 128 if(size < 0) 129 return buf->buf; 130 131 if(!buf->buf) { 132 buf->buf = malloc(size); 133 if(buf->buf) 134 buf->size = size; 135 136 return buf->buf; 137 } 138 139 if((unsigned long) size <= buf->size) { 140 /* Shorten the buffer only if it frees a significant byte count. This 141 avoids some realloc() overhead. */ 142 143 if(buf->size - size < MIN_BYTE_GAIN) 144 return buf->buf; 145 } 146 147 /* Resize the buffer. */ 148 149 cp = realloc(buf->buf, size); 150 if(cp) { 151 buf->buf = cp; 152 buf->size = size; 153 } 154 else if(size <= buf->size) 155 cp = buf->buf; 156 157 return cp; 158 } 159 160 161 static char * 162 buffer_unthreaded(localkey_t key, long size) 163 { 164 return get_buffer(locbufs + key, size); 165 } 166 167 168 static char * 169 buffer_threaded(localkey_t key, long size) 170 { 171 struct buffer_t *bufs; 172 173 /* Get the buffer for the given local key in the current thread, and 174 make sure it is at least `size'-byte long. Set `size' to < 0 to get 175 its address only. */ 176 177 bufs = (struct buffer_t *) pthread_getspecific(thdkey); 178 179 if(!bufs) { 180 if(size < 0) 181 return (char *) NULL; /* No buffer yet. */ 182 183 /* Allocate buffer descriptors for the current thread. */ 184 185 bufs = calloc((size_t) LK_LAST, sizeof(*bufs)); 186 if(!bufs) 187 return (char *) NULL; 188 189 if(pthread_setspecific(thdkey, (void *) bufs)) { 190 free(bufs); 191 return (char *) NULL; 192 } 193 } 194 195 return get_buffer(bufs + key, size); 196 } 197 198 199 static char * 200 buffer_undef(localkey_t key, long size) 201 { 202 /* Define the buffer system, get the buffer for the given local key in 203 the current thread, and make sure it is at least `size'-byte long. 204 Set `size' to < 0 to get its address only. */ 205 206 pthread_mutex_lock(&mutex); 207 208 /* Determine if we can use pthread-specific data. */ 209 210 if(Curl_thread_buffer == buffer_undef) { /* If unchanged during lock. */ 211 if(!pthread_key_create(&thdkey, thdbufdestroy)) 212 Curl_thread_buffer = buffer_threaded; 213 else { 214 locbufs = calloc((size_t) LK_LAST, sizeof(*locbufs)); 215 if(!locbufs) { 216 pthread_mutex_unlock(&mutex); 217 return (char *) NULL; 218 } 219 else 220 Curl_thread_buffer = buffer_unthreaded; 221 } 222 223 atexit(terminate); 224 } 225 226 pthread_mutex_unlock(&mutex); 227 return Curl_thread_buffer(key, size); 228 } 229 230 231 static char * 232 set_thread_string(localkey_t key, const char *s) 233 { 234 int i; 235 char *cp; 236 237 if(!s) 238 return (char *) NULL; 239 240 i = strlen(s) + 1; 241 cp = Curl_thread_buffer(key, MAX_CONV_EXPANSION * i + 1); 242 243 if(cp) { 244 i = QadrtConvertE2A(cp, s, MAX_CONV_EXPANSION * i, i); 245 cp[i] = '\0'; 246 } 247 248 return cp; 249 } 250 251 252 int 253 Curl_getnameinfo_a(const struct sockaddr *sa, socklen_t salen, 254 char *nodename, socklen_t nodenamelen, 255 char *servname, socklen_t servnamelen, 256 int flags) 257 { 258 char *enodename = NULL; 259 char *eservname = NULL; 260 int status; 261 262 if(nodename && nodenamelen) { 263 enodename = malloc(nodenamelen); 264 if(!enodename) 265 return EAI_MEMORY; 266 } 267 268 if(servname && servnamelen) { 269 eservname = malloc(servnamelen); 270 if(!eservname) { 271 free(enodename); 272 return EAI_MEMORY; 273 } 274 } 275 276 status = getnameinfo(sa, salen, enodename, nodenamelen, 277 eservname, servnamelen, flags); 278 279 if(!status) { 280 int i; 281 if(enodename) { 282 i = QadrtConvertE2A(nodename, enodename, 283 nodenamelen - 1, strlen(enodename)); 284 nodename[i] = '\0'; 285 } 286 287 if(eservname) { 288 i = QadrtConvertE2A(servname, eservname, 289 servnamelen - 1, strlen(eservname)); 290 servname[i] = '\0'; 291 } 292 } 293 294 free(enodename); 295 free(eservname); 296 return status; 297 } 298 299 int 300 Curl_getaddrinfo_a(const char *nodename, const char *servname, 301 const struct addrinfo *hints, 302 struct addrinfo **res) 303 { 304 char *enodename; 305 char *eservname; 306 int status; 307 int i; 308 309 enodename = (char *) NULL; 310 eservname = (char *) NULL; 311 312 if(nodename) { 313 i = strlen(nodename); 314 315 enodename = malloc(i + 1); 316 if(!enodename) 317 return EAI_MEMORY; 318 319 i = QadrtConvertA2E(enodename, nodename, i, i); 320 enodename[i] = '\0'; 321 } 322 323 if(servname) { 324 i = strlen(servname); 325 326 eservname = malloc(i + 1); 327 if(!eservname) { 328 free(enodename); 329 return EAI_MEMORY; 330 } 331 332 QadrtConvertA2E(eservname, servname, i, i); 333 eservname[i] = '\0'; 334 } 335 336 status = getaddrinfo(enodename, eservname, hints, res); 337 free(enodename); 338 free(eservname); 339 return status; 340 } 341 342 #ifdef HAVE_GSSAPI 343 344 /* ASCII wrappers for the GSSAPI procedures. */ 345 346 static int 347 Curl_gss_convert_in_place(OM_uint32 *minor_status, gss_buffer_t buf) 348 { 349 unsigned int i = buf->length; 350 351 /* Convert `buf' in place, from EBCDIC to ASCII. 352 If error, release the buffer and return -1. Else return 0. */ 353 354 if(i) { 355 char *t = malloc(i); 356 if(!t) { 357 gss_release_buffer(minor_status, buf); 358 359 if(minor_status) 360 /* !checksrc! disable ERRNOVAR 1 */ 361 *minor_status = ENOMEM; 362 363 return -1; 364 } 365 366 QadrtConvertE2A(t, buf->value, i, i); 367 memcpy(buf->value, t, i); 368 free(t); 369 } 370 371 return 0; 372 } 373 374 375 OM_uint32 376 Curl_gss_import_name_a(OM_uint32 *minor_status, gss_buffer_t in_name, 377 gss_OID in_name_type, gss_name_t *out_name) 378 { 379 OM_uint32 rc; 380 unsigned int i; 381 gss_buffer_desc in; 382 383 if(!in_name || !in_name->value || !in_name->length) 384 return gss_import_name(minor_status, in_name, in_name_type, out_name); 385 386 memcpy((char *) &in, (char *) in_name, sizeof(in)); 387 i = in.length; 388 389 in.value = malloc(i + 1); 390 if(!in.value) { 391 if(minor_status) 392 /* !checksrc! disable ERRNOVAR 1 */ 393 *minor_status = ENOMEM; 394 395 return GSS_S_FAILURE; 396 } 397 398 QadrtConvertA2E(in.value, in_name->value, i, i); 399 ((char *) in.value)[i] = '\0'; 400 rc = gss_import_name(minor_status, &in, in_name_type, out_name); 401 free(in.value); 402 return rc; 403 } 404 405 OM_uint32 406 Curl_gss_display_status_a(OM_uint32 *minor_status, OM_uint32 status_value, 407 int status_type, gss_OID mech_type, 408 gss_msg_ctx_t *message_context, 409 gss_buffer_t status_string) 410 { 411 int rc; 412 413 rc = gss_display_status(minor_status, status_value, status_type, 414 mech_type, message_context, status_string); 415 416 if(rc != GSS_S_COMPLETE || !status_string || 417 !status_string->length || !status_string->value) 418 return rc; 419 420 /* No way to allocate a buffer here, because it will be released by 421 gss_release_buffer(). The solution is to overwrite the EBCDIC buffer 422 with ASCII to return it. */ 423 424 if(Curl_gss_convert_in_place(minor_status, status_string)) 425 return GSS_S_FAILURE; 426 427 return rc; 428 } 429 430 OM_uint32 431 Curl_gss_init_sec_context_a(OM_uint32 *minor_status, 432 gss_cred_id_t cred_handle, 433 gss_ctx_id_t *context_handle, 434 gss_name_t target_name, gss_OID mech_type, 435 gss_flags_t req_flags, OM_uint32 time_req, 436 gss_channel_bindings_t input_chan_bindings, 437 gss_buffer_t input_token, 438 gss_OID *actual_mech_type, 439 gss_buffer_t output_token, gss_flags_t *ret_flags, 440 OM_uint32 *time_rec) 441 { 442 int rc; 443 gss_buffer_desc in; 444 gss_buffer_t inp; 445 446 in.value = NULL; 447 inp = input_token; 448 449 if(inp) { 450 if(inp->length && inp->value) { 451 unsigned int i = inp->length; 452 453 in.value = malloc(i + 1); 454 if(!in.value) { 455 if(minor_status) 456 /* !checksrc! disable ERRNOVAR 1 */ 457 *minor_status = ENOMEM; 458 459 return GSS_S_FAILURE; 460 } 461 462 QadrtConvertA2E(in.value, input_token->value, i, i); 463 ((char *) in.value)[i] = '\0'; 464 in.length = i; 465 inp = ∈ 466 } 467 } 468 469 rc = gss_init_sec_context(minor_status, cred_handle, context_handle, 470 target_name, mech_type, req_flags, time_req, 471 input_chan_bindings, inp, actual_mech_type, 472 output_token, ret_flags, time_rec); 473 free(in.value); 474 475 if(rc != GSS_S_COMPLETE || !output_token || 476 !output_token->length || !output_token->value) 477 return rc; 478 479 /* No way to allocate a buffer here, because it will be released by 480 gss_release_buffer(). The solution is to overwrite the EBCDIC buffer 481 with ASCII to return it. */ 482 483 if(Curl_gss_convert_in_place(minor_status, output_token)) 484 return GSS_S_FAILURE; 485 486 return rc; 487 } 488 489 490 OM_uint32 491 Curl_gss_delete_sec_context_a(OM_uint32 *minor_status, 492 gss_ctx_id_t *context_handle, 493 gss_buffer_t output_token) 494 { 495 OM_uint32 rc; 496 497 rc = gss_delete_sec_context(minor_status, context_handle, output_token); 498 499 if(rc != GSS_S_COMPLETE || !output_token || 500 !output_token->length || !output_token->value) 501 return rc; 502 503 /* No way to allocate a buffer here, because it will be released by 504 gss_release_buffer(). The solution is to overwrite the EBCDIC buffer 505 with ASCII to return it. */ 506 507 if(Curl_gss_convert_in_place(minor_status, output_token)) 508 return GSS_S_FAILURE; 509 510 return rc; 511 } 512 513 #endif /* HAVE_GSSAPI */ 514 515 #ifndef CURL_DISABLE_LDAP 516 517 /* ASCII wrappers for the LDAP procedures. */ 518 519 void * 520 Curl_ldap_init_a(char *host, int port) 521 { 522 size_t i; 523 char *ehost; 524 void *result; 525 526 if(!host) 527 return (void *) ldap_init(host, port); 528 529 i = strlen(host); 530 531 ehost = malloc(i + 1); 532 if(!ehost) 533 return (void *) NULL; 534 535 QadrtConvertA2E(ehost, host, i, i); 536 ehost[i] = '\0'; 537 result = (void *) ldap_init(ehost, port); 538 free(ehost); 539 return result; 540 } 541 542 int 543 Curl_ldap_simple_bind_s_a(void *ld, char *dn, char *passwd) 544 { 545 int i; 546 char *edn; 547 char *epasswd; 548 549 edn = (char *) NULL; 550 epasswd = (char *) NULL; 551 552 if(dn) { 553 i = strlen(dn); 554 555 edn = malloc(i + 1); 556 if(!edn) 557 return LDAP_NO_MEMORY; 558 559 QadrtConvertA2E(edn, dn, i, i); 560 edn[i] = '\0'; 561 } 562 563 if(passwd) { 564 i = strlen(passwd); 565 566 epasswd = malloc(i + 1); 567 if(!epasswd) { 568 free(edn); 569 return LDAP_NO_MEMORY; 570 } 571 572 QadrtConvertA2E(epasswd, passwd, i, i); 573 epasswd[i] = '\0'; 574 } 575 576 i = ldap_simple_bind_s(ld, edn, epasswd); 577 free(epasswd); 578 free(edn); 579 return i; 580 } 581 582 int 583 Curl_ldap_search_s_a(void *ld, char *base, int scope, char *filter, 584 char **attrs, int attrsonly, LDAPMessage **res) 585 { 586 int i; 587 int j; 588 char *ebase; 589 char *efilter; 590 char **eattrs; 591 int status; 592 593 ebase = (char *) NULL; 594 efilter = (char *) NULL; 595 eattrs = (char **) NULL; 596 status = LDAP_SUCCESS; 597 598 if(base) { 599 i = strlen(base); 600 601 ebase = malloc(i + 1); 602 if(!ebase) 603 status = LDAP_NO_MEMORY; 604 else { 605 QadrtConvertA2E(ebase, base, i, i); 606 ebase[i] = '\0'; 607 } 608 } 609 610 if(filter && status == LDAP_SUCCESS) { 611 i = strlen(filter); 612 613 efilter = malloc(i + 1); 614 if(!efilter) 615 status = LDAP_NO_MEMORY; 616 else { 617 QadrtConvertA2E(efilter, filter, i, i); 618 efilter[i] = '\0'; 619 } 620 } 621 622 if(attrs && status == LDAP_SUCCESS) { 623 for(i = 0; attrs[i++];) 624 ; 625 626 eattrs = calloc(i, sizeof(*eattrs)); 627 if(!eattrs) 628 status = LDAP_NO_MEMORY; 629 else { 630 for(j = 0; attrs[j]; j++) { 631 i = strlen(attrs[j]); 632 633 eattrs[j] = malloc(i + 1); 634 if(!eattrs[j]) { 635 status = LDAP_NO_MEMORY; 636 break; 637 } 638 639 QadrtConvertA2E(eattrs[j], attrs[j], i, i); 640 eattrs[j][i] = '\0'; 641 } 642 } 643 } 644 645 if(status == LDAP_SUCCESS) 646 status = ldap_search_s(ld, ebase ? ebase : "", scope, 647 efilter ? efilter : "(objectclass=*)", 648 eattrs, attrsonly, res); 649 650 if(eattrs) { 651 for(j = 0; eattrs[j]; j++) 652 free(eattrs[j]); 653 654 free(eattrs); 655 } 656 657 free(efilter); 658 free(ebase); 659 return status; 660 } 661 662 663 struct berval ** 664 Curl_ldap_get_values_len_a(void *ld, LDAPMessage *entry, const char *attr) 665 { 666 char *cp; 667 struct berval **result; 668 669 cp = (char *) NULL; 670 671 if(attr) { 672 int i = strlen(attr); 673 674 cp = malloc(i + 1); 675 if(!cp) { 676 ldap_set_lderrno(ld, LDAP_NO_MEMORY, NULL, 677 ldap_err2string(LDAP_NO_MEMORY)); 678 return (struct berval **) NULL; 679 } 680 681 QadrtConvertA2E(cp, attr, i, i); 682 cp[i] = '\0'; 683 } 684 685 result = ldap_get_values_len(ld, entry, cp); 686 free(cp); 687 688 /* Result data are binary in nature, so they haven't been 689 converted to EBCDIC. Therefore do not convert. */ 690 691 return result; 692 } 693 694 char * 695 Curl_ldap_err2string_a(int error) 696 { 697 return set_thread_string(LK_LDAP_ERROR, ldap_err2string(error)); 698 } 699 700 char * 701 Curl_ldap_get_dn_a(void *ld, LDAPMessage *entry) 702 { 703 int i; 704 char *cp; 705 char *cp2; 706 707 cp = ldap_get_dn(ld, entry); 708 709 if(!cp) 710 return cp; 711 712 i = strlen(cp); 713 714 cp2 = malloc(i + 1); 715 if(!cp2) 716 return cp2; 717 718 QadrtConvertE2A(cp2, cp, i, i); 719 cp2[i] = '\0'; 720 721 /* No way to allocate a buffer here, because it will be released by 722 ldap_memfree() and ldap_memalloc() does not exist. The solution is to 723 overwrite the EBCDIC buffer with ASCII to return it. */ 724 725 strcpy(cp, cp2); 726 free(cp2); 727 return cp; 728 } 729 730 char * 731 Curl_ldap_first_attribute_a(void *ld, 732 LDAPMessage *entry, BerElement **berptr) 733 { 734 int i; 735 char *cp; 736 char *cp2; 737 738 cp = ldap_first_attribute(ld, entry, berptr); 739 740 if(!cp) 741 return cp; 742 743 i = strlen(cp); 744 745 cp2 = malloc(i + 1); 746 if(!cp2) 747 return cp2; 748 749 QadrtConvertE2A(cp2, cp, i, i); 750 cp2[i] = '\0'; 751 752 /* No way to allocate a buffer here, because it will be released by 753 ldap_memfree() and ldap_memalloc() does not exist. The solution is to 754 overwrite the EBCDIC buffer with ASCII to return it. */ 755 756 strcpy(cp, cp2); 757 free(cp2); 758 return cp; 759 } 760 761 char * 762 Curl_ldap_next_attribute_a(void *ld, 763 LDAPMessage *entry, BerElement *berptr) 764 { 765 int i; 766 char *cp; 767 char *cp2; 768 769 cp = ldap_next_attribute(ld, entry, berptr); 770 771 if(!cp) 772 return cp; 773 774 i = strlen(cp); 775 776 cp2 = malloc(i + 1); 777 if(!cp2) 778 return cp2; 779 780 QadrtConvertE2A(cp2, cp, i, i); 781 cp2[i] = '\0'; 782 783 /* No way to allocate a buffer here, because it will be released by 784 ldap_memfree() and ldap_memalloc() does not exist. The solution is to 785 overwrite the EBCDIC buffer with ASCII to return it. */ 786 787 strcpy(cp, cp2); 788 free(cp2); 789 return cp; 790 } 791 792 #endif /* CURL_DISABLE_LDAP */ 793 794 static int 795 sockaddr2ebcdic(struct sockaddr_storage *dstaddr, 796 const struct sockaddr *srcaddr, int srclen) 797 { 798 const struct sockaddr_un *srcu; 799 struct sockaddr_un *dstu; 800 unsigned int i; 801 unsigned int dstsize; 802 803 /* Convert a socket address to job CCSID, if needed. */ 804 805 if(!srcaddr || srclen < offsetof(struct sockaddr, sa_family) + 806 sizeof(srcaddr->sa_family) || srclen > sizeof(*dstaddr)) { 807 /* !checksrc! disable ERRNOVAR 1 */ 808 errno = EINVAL; 809 return -1; 810 } 811 812 memcpy((char *) dstaddr, (char *) srcaddr, srclen); 813 814 switch(srcaddr->sa_family) { 815 816 case AF_UNIX: 817 srcu = (const struct sockaddr_un *) srcaddr; 818 dstu = (struct sockaddr_un *) dstaddr; 819 dstsize = sizeof(*dstaddr) - offsetof(struct sockaddr_un, sun_path); 820 srclen -= offsetof(struct sockaddr_un, sun_path); 821 i = QadrtConvertA2E(dstu->sun_path, srcu->sun_path, dstsize - 1, srclen); 822 dstu->sun_path[i] = '\0'; 823 srclen = i + offsetof(struct sockaddr_un, sun_path); 824 } 825 826 return srclen; 827 } 828 829 830 static int 831 sockaddr2ascii(struct sockaddr *dstaddr, int dstlen, 832 const struct sockaddr_storage *srcaddr, int srclen) 833 { 834 const struct sockaddr_un *srcu; 835 struct sockaddr_un *dstu; 836 unsigned int dstsize; 837 838 /* Convert a socket address to ASCII, if needed. */ 839 840 if(!srclen) 841 return 0; 842 if(srclen > dstlen) 843 srclen = dstlen; 844 if(!srcaddr || srclen < 0) { 845 /* !checksrc! disable ERRNOVAR 1 */ 846 errno = EINVAL; 847 return -1; 848 } 849 850 memcpy((char *) dstaddr, (char *) srcaddr, srclen); 851 852 if(srclen >= offsetof(struct sockaddr_storage, ss_family) + 853 sizeof(srcaddr->ss_family)) { 854 switch(srcaddr->ss_family) { 855 856 case AF_UNIX: 857 srcu = (const struct sockaddr_un *) srcaddr; 858 dstu = (struct sockaddr_un *) dstaddr; 859 dstsize = dstlen - offsetof(struct sockaddr_un, sun_path); 860 srclen -= offsetof(struct sockaddr_un, sun_path); 861 if(dstsize > 0 && srclen > 0) { 862 srclen = QadrtConvertE2A(dstu->sun_path, srcu->sun_path, 863 dstsize - 1, srclen); 864 dstu->sun_path[srclen] = '\0'; 865 } 866 srclen += offsetof(struct sockaddr_un, sun_path); 867 } 868 } 869 870 return srclen; 871 } 872 873 int 874 Curl_os400_connect(int sd, struct sockaddr *destaddr, int addrlen) 875 { 876 int i; 877 struct sockaddr_storage laddr; 878 879 i = sockaddr2ebcdic(&laddr, destaddr, addrlen); 880 881 if(i < 0) 882 return -1; 883 884 return connect(sd, (struct sockaddr *) &laddr, i); 885 } 886 887 int 888 Curl_os400_bind(int sd, struct sockaddr *localaddr, int addrlen) 889 { 890 int i; 891 struct sockaddr_storage laddr; 892 893 i = sockaddr2ebcdic(&laddr, localaddr, addrlen); 894 895 if(i < 0) 896 return -1; 897 898 return bind(sd, (struct sockaddr *) &laddr, i); 899 } 900 901 int 902 Curl_os400_sendto(int sd, char *buffer, int buflen, int flags, 903 const struct sockaddr *dstaddr, int addrlen) 904 { 905 int i; 906 struct sockaddr_storage laddr; 907 908 i = sockaddr2ebcdic(&laddr, dstaddr, addrlen); 909 910 if(i < 0) 911 return -1; 912 913 return sendto(sd, buffer, buflen, flags, (struct sockaddr *) &laddr, i); 914 } 915 916 int 917 Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags, 918 struct sockaddr *fromaddr, int *addrlen) 919 { 920 int rcvlen; 921 struct sockaddr_storage laddr; 922 int laddrlen = sizeof(laddr); 923 924 if(!fromaddr || !addrlen || *addrlen <= 0) 925 return recvfrom(sd, buffer, buflen, flags, fromaddr, addrlen); 926 927 laddr.ss_family = AF_UNSPEC; /* To detect if unused. */ 928 rcvlen = recvfrom(sd, buffer, buflen, flags, 929 (struct sockaddr *) &laddr, &laddrlen); 930 931 if(rcvlen < 0) 932 return rcvlen; 933 934 if(laddr.ss_family == AF_UNSPEC) 935 laddrlen = 0; 936 else { 937 laddrlen = sockaddr2ascii(fromaddr, *addrlen, &laddr, laddrlen); 938 if(laddrlen < 0) 939 return laddrlen; 940 } 941 *addrlen = laddrlen; 942 return rcvlen; 943 } 944 945 int 946 Curl_os400_getpeername(int sd, struct sockaddr *addr, int *addrlen) 947 { 948 struct sockaddr_storage laddr; 949 int laddrlen = sizeof(laddr); 950 int retcode = getpeername(sd, (struct sockaddr *) &laddr, &laddrlen); 951 952 if(!retcode) { 953 laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen); 954 if(laddrlen < 0) 955 return laddrlen; 956 *addrlen = laddrlen; 957 } 958 959 return retcode; 960 } 961 962 int 963 Curl_os400_getsockname(int sd, struct sockaddr *addr, int *addrlen) 964 { 965 struct sockaddr_storage laddr; 966 int laddrlen = sizeof(laddr); 967 int retcode = getsockname(sd, (struct sockaddr *) &laddr, &laddrlen); 968 969 if(!retcode) { 970 laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen); 971 if(laddrlen < 0) 972 return laddrlen; 973 *addrlen = laddrlen; 974 } 975 976 return retcode; 977 } 978 979 980 #ifdef HAVE_LIBZ 981 const char * 982 Curl_os400_zlibVersion(void) 983 { 984 return set_thread_string(LK_ZLIB_VERSION, zlibVersion()); 985 } 986 987 988 int 989 Curl_os400_inflateInit_(z_streamp strm, const char *version, int stream_size) 990 { 991 z_const char *msgb4 = strm->msg; 992 int ret; 993 994 ret = inflateInit(strm); 995 996 if(strm->msg != msgb4) 997 strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); 998 999 return ret; 1000 } 1001 1002 int 1003 Curl_os400_inflateInit2_(z_streamp strm, int windowBits, 1004 const char *version, int stream_size) 1005 { 1006 z_const char *msgb4 = strm->msg; 1007 int ret; 1008 1009 ret = inflateInit2(strm, windowBits); 1010 1011 if(strm->msg != msgb4) 1012 strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); 1013 1014 return ret; 1015 } 1016 1017 int 1018 Curl_os400_inflate(z_streamp strm, int flush) 1019 { 1020 z_const char *msgb4 = strm->msg; 1021 int ret; 1022 1023 ret = inflate(strm, flush); 1024 1025 if(strm->msg != msgb4) 1026 strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); 1027 1028 return ret; 1029 } 1030 1031 int 1032 Curl_os400_inflateEnd(z_streamp strm) 1033 { 1034 z_const char *msgb4 = strm->msg; 1035 int ret; 1036 1037 ret = inflateEnd(strm); 1038 1039 if(strm->msg != msgb4) 1040 strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); 1041 1042 return ret; 1043 } 1044 1045 #endif