Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/thirdparty/curl/packages/OS400/os400sys.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/thirdparty/curl/packages/OS400/os400sys.c Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,1444 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * + ***************************************************************************/ + +/* OS/400 additional support. */ + +#include <curl/curl.h> +#include "config-os400.h" /* Not curl_setup.h: we only need some defines. */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <pthread.h> +#include <netdb.h> +#include <qadrt.h> +#include <errno.h> + +#ifdef HAVE_ZLIB_H +#include <zlib.h> +#endif + +#ifdef USE_GSKIT +#include <gskssl.h> +#include <qsoasync.h> +#endif + +#ifdef HAVE_GSSAPI +#include <gssapi.h> +#endif + +#ifndef CURL_DISABLE_LDAP +#include <ldap.h> +#endif + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "os400sys.h" + + +/** +*** QADRT OS/400 ASCII runtime defines only the most used procedures, but +*** but a lot of them are not supported. This module implements +*** ASCII wrappers for those that are used by libcurl, but not +*** defined by QADRT. +**/ + +#pragma convert(0) /* Restore EBCDIC. */ + + +#define MIN_BYTE_GAIN 1024 /* Minimum gain when shortening a buffer. */ + +typedef struct { + unsigned long size; /* Buffer size. */ + char * buf; /* Buffer address. */ +} buffer_t; + + +static char * buffer_undef(localkey_t key, long size); +static char * buffer_threaded(localkey_t key, long size); +static char * buffer_unthreaded(localkey_t key, long size); + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_key_t thdkey; +static buffer_t * locbufs; + +char * (* Curl_thread_buffer)(localkey_t key, long size) = buffer_undef; + + +static void +thdbufdestroy(void * private) + +{ + if(private) { + buffer_t * p = (buffer_t *) private; + localkey_t i; + + for(i = (localkey_t) 0; i < LK_LAST; i++) { + free(p->buf); + p++; + } + + free(private); + } +} + + +static void +terminate(void) + +{ + if(Curl_thread_buffer == buffer_threaded) { + locbufs = pthread_getspecific(thdkey); + pthread_setspecific(thdkey, (void *) NULL); + pthread_key_delete(thdkey); + } + + if(Curl_thread_buffer != buffer_undef) { + thdbufdestroy((void *) locbufs); + locbufs = (buffer_t *) NULL; + } + + Curl_thread_buffer = buffer_undef; +} + + +static char * +get_buffer(buffer_t * buf, long size) + +{ + char * cp; + + /* If `size' >= 0, make sure buffer at `buf' is at least `size'-byte long. + Return the buffer address. */ + + if(size < 0) + return buf->buf; + + if(!buf->buf) { + buf->buf = malloc(size); + if(buf->buf) + buf->size = size; + + return buf->buf; + } + + if((unsigned long) size <= buf->size) { + /* Shorten the buffer only if it frees a significant byte count. This + avoids some realloc() overhead. */ + + if(buf->size - size < MIN_BYTE_GAIN) + return buf->buf; + } + + /* Resize the buffer. */ + + cp = realloc(buf->buf, size); + if(cp) { + buf->buf = cp; + buf->size = size; + } + else if(size <= buf->size) + cp = buf->buf; + + return cp; +} + + +static char * +buffer_unthreaded(localkey_t key, long size) + +{ + return get_buffer(locbufs + key, size); +} + + +static char * +buffer_threaded(localkey_t key, long size) + +{ + buffer_t * bufs; + + /* Get the buffer for the given local key in the current thread, and + make sure it is at least `size'-byte long. Set `size' to < 0 to get + its address only. */ + + bufs = (buffer_t *) pthread_getspecific(thdkey); + + if(!bufs) { + if(size < 0) + return (char *) NULL; /* No buffer yet. */ + + /* Allocate buffer descriptors for the current thread. */ + + bufs = calloc((size_t) LK_LAST, sizeof *bufs); + if(!bufs) + return (char *) NULL; + + if(pthread_setspecific(thdkey, (void *) bufs)) { + free(bufs); + return (char *) NULL; + } + } + + return get_buffer(bufs + key, size); +} + + +static char * +buffer_undef(localkey_t key, long size) + +{ + /* Define the buffer system, get the buffer for the given local key in + the current thread, and make sure it is at least `size'-byte long. + Set `size' to < 0 to get its address only. */ + + pthread_mutex_lock(&mutex); + + /* Determine if we can use pthread-specific data. */ + + if(Curl_thread_buffer == buffer_undef) { /* If unchanged during lock. */ + if(!pthread_key_create(&thdkey, thdbufdestroy)) + Curl_thread_buffer = buffer_threaded; + else if(!(locbufs = calloc((size_t) LK_LAST, sizeof *locbufs))) { + pthread_mutex_unlock(&mutex); + return (char *) NULL; + } + else + Curl_thread_buffer = buffer_unthreaded; + + atexit(terminate); + } + + pthread_mutex_unlock(&mutex); + return Curl_thread_buffer(key, size); +} + + +static char * +set_thread_string(localkey_t key, const char * s) + +{ + int i; + char * cp; + + if(!s) + return (char *) NULL; + + i = strlen(s) + 1; + cp = Curl_thread_buffer(key, MAX_CONV_EXPANSION * i + 1); + + if(cp) { + i = QadrtConvertE2A(cp, s, MAX_CONV_EXPANSION * i, i); + cp[i] = '\0'; + } + + return cp; +} + + +int +Curl_getnameinfo_a(const struct sockaddr * sa, curl_socklen_t salen, + char * nodename, curl_socklen_t nodenamelen, + char * servname, curl_socklen_t servnamelen, + int flags) + +{ + char *enodename = NULL; + char *eservname = NULL; + int status; + + if(nodename && nodenamelen) { + enodename = malloc(nodenamelen); + if(!enodename) + return EAI_MEMORY; + } + + if(servname && servnamelen) { + eservname = malloc(servnamelen); + if(!eservname) { + free(enodename); + return EAI_MEMORY; + } + } + + status = getnameinfo(sa, salen, enodename, nodenamelen, + eservname, servnamelen, flags); + + if(!status) { + int i; + if(enodename) { + i = QadrtConvertE2A(nodename, enodename, + nodenamelen - 1, strlen(enodename)); + nodename[i] = '\0'; + } + + if(eservname) { + i = QadrtConvertE2A(servname, eservname, + servnamelen - 1, strlen(eservname)); + servname[i] = '\0'; + } + } + + free(enodename); + free(eservname); + return status; +} + + +int +Curl_getaddrinfo_a(const char * nodename, const char * servname, + const struct addrinfo * hints, + struct addrinfo * * res) + +{ + char * enodename; + char * eservname; + int status; + int i; + + enodename = (char *) NULL; + eservname = (char *) NULL; + + if(nodename) { + i = strlen(nodename); + + enodename = malloc(i + 1); + if(!enodename) + return EAI_MEMORY; + + i = QadrtConvertA2E(enodename, nodename, i, i); + enodename[i] = '\0'; + } + + if(servname) { + i = strlen(servname); + + eservname = malloc(i + 1); + if(!eservname) { + free(enodename); + return EAI_MEMORY; + } + + QadrtConvertA2E(eservname, servname, i, i); + eservname[i] = '\0'; + } + + status = getaddrinfo(enodename, eservname, hints, res); + free(enodename); + free(eservname); + return status; +} + + +#ifdef USE_GSKIT + +/* ASCII wrappers for the GSKit procedures. */ + +/* + * EBCDIC --> ASCII string mapping table. + * Some strings returned by GSKit are dynamically allocated and automatically + * released when closing the handle. + * To provide the same functionality, we use a "private" handle that + * holds the GSKit handle and a list of string mappings. This will allow + * avoid conversion of already converted strings and releasing them upon + * close time. + */ + +struct gskstrlist { + struct gskstrlist * next; + const char * ebcdicstr; + const char * asciistr; +}; + +struct Curl_gsk_descriptor { + gsk_handle h; + struct gskstrlist * strlist; +}; + + +int +Curl_gsk_environment_open(gsk_handle * my_env_handle) + +{ + struct Curl_gsk_descriptor * p; + int rc; + + if(!my_env_handle) + return GSK_OS400_ERROR_INVALID_POINTER; + p = (struct Curl_gsk_descriptor *) malloc(sizeof *p); + if(!p) + return GSK_INSUFFICIENT_STORAGE; + p->strlist = (struct gskstrlist *) NULL; + rc = gsk_environment_open(&p->h); + if(rc != GSK_OK) + free(p); + else + *my_env_handle = (gsk_handle) p; + return rc; +} + + +int +Curl_gsk_secure_soc_open(gsk_handle my_env_handle, + gsk_handle * my_session_handle) + +{ + struct Curl_gsk_descriptor * p; + gsk_handle h; + int rc; + + if(!my_env_handle) + return GSK_INVALID_HANDLE; + if(!my_session_handle) + return GSK_OS400_ERROR_INVALID_POINTER; + h = ((struct Curl_gsk_descriptor *) my_env_handle)->h; + p = (struct Curl_gsk_descriptor *) malloc(sizeof *p); + if(!p) + return GSK_INSUFFICIENT_STORAGE; + p->strlist = (struct gskstrlist *) NULL; + rc = gsk_secure_soc_open(h, &p->h); + if(rc != GSK_OK) + free(p); + else + *my_session_handle = (gsk_handle) p; + return rc; +} + + +static void +gsk_free_handle(struct Curl_gsk_descriptor * p) + +{ + struct gskstrlist * q; + + while((q = p->strlist)) { + p->strlist = q; + free((void *) q->asciistr); + free(q); + } + free(p); +} + + +int +Curl_gsk_environment_close(gsk_handle * my_env_handle) + +{ + struct Curl_gsk_descriptor * p; + int rc; + + if(!my_env_handle) + return GSK_OS400_ERROR_INVALID_POINTER; + if(!*my_env_handle) + return GSK_INVALID_HANDLE; + p = (struct Curl_gsk_descriptor *) *my_env_handle; + rc = gsk_environment_close(&p->h); + if(rc == GSK_OK) { + gsk_free_handle(p); + *my_env_handle = (gsk_handle) NULL; + } + return rc; +} + + +int +Curl_gsk_secure_soc_close(gsk_handle * my_session_handle) + +{ + struct Curl_gsk_descriptor * p; + int rc; + + if(!my_session_handle) + return GSK_OS400_ERROR_INVALID_POINTER; + if(!*my_session_handle) + return GSK_INVALID_HANDLE; + p = (struct Curl_gsk_descriptor *) *my_session_handle; + rc = gsk_secure_soc_close(&p->h); + if(rc == GSK_OK) { + gsk_free_handle(p); + *my_session_handle = (gsk_handle) NULL; + } + return rc; +} + + +int +Curl_gsk_environment_init(gsk_handle my_env_handle) + +{ + struct Curl_gsk_descriptor * p; + + if(!my_env_handle) + return GSK_INVALID_HANDLE; + p = (struct Curl_gsk_descriptor *) my_env_handle; + return gsk_environment_init(p->h); +} + + +int +Curl_gsk_secure_soc_init(gsk_handle my_session_handle) + +{ + struct Curl_gsk_descriptor * p; + + if(!my_session_handle) + return GSK_INVALID_HANDLE; + p = (struct Curl_gsk_descriptor *) my_session_handle; + return gsk_secure_soc_init(p->h); +} + + +int +Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID, + const char * buffer, int bufSize) + +{ + struct Curl_gsk_descriptor * p; + char * ebcdicbuf; + int rc; + + if(!my_gsk_handle) + return GSK_INVALID_HANDLE; + if(!buffer) + return GSK_OS400_ERROR_INVALID_POINTER; + if(bufSize < 0) + return GSK_ATTRIBUTE_INVALID_LENGTH; + p = (struct Curl_gsk_descriptor *) my_gsk_handle; + if(!bufSize) + bufSize = strlen(buffer); + ebcdicbuf = malloc(bufSize + 1); + if(!ebcdicbuf) + return GSK_INSUFFICIENT_STORAGE; + QadrtConvertA2E(ebcdicbuf, buffer, bufSize, bufSize); + ebcdicbuf[bufSize] = '\0'; + rc = gsk_attribute_set_buffer(p->h, bufID, ebcdicbuf, bufSize); + free(ebcdicbuf); + return rc; +} + + +int +Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID, + GSK_ENUM_VALUE enumValue) + +{ + struct Curl_gsk_descriptor * p; + + if(!my_gsk_handle) + return GSK_INVALID_HANDLE; + p = (struct Curl_gsk_descriptor *) my_gsk_handle; + return gsk_attribute_set_enum(p->h, enumID, enumValue); +} + + +int +Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle, + GSK_NUM_ID numID, int numValue) + +{ + struct Curl_gsk_descriptor * p; + + if(!my_gsk_handle) + return GSK_INVALID_HANDLE; + p = (struct Curl_gsk_descriptor *) my_gsk_handle; + return gsk_attribute_set_numeric_value(p->h, numID, numValue); +} + + +int +Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle, + GSK_CALLBACK_ID callBackID, + void * callBackAreaPtr) + +{ + struct Curl_gsk_descriptor * p; + + if(!my_gsk_handle) + return GSK_INVALID_HANDLE; + p = (struct Curl_gsk_descriptor *) my_gsk_handle; + return gsk_attribute_set_callback(p->h, callBackID, callBackAreaPtr); +} + + +static int +cachestring(struct Curl_gsk_descriptor * p, + const char * ebcdicbuf, int bufsize, const char * * buffer) + +{ + int rc; + char * asciibuf; + struct gskstrlist * sp; + + for(sp = p->strlist; sp; sp = sp->next) + if(sp->ebcdicstr == ebcdicbuf) + break; + if(!sp) { + sp = (struct gskstrlist *) malloc(sizeof *sp); + if(!sp) + return GSK_INSUFFICIENT_STORAGE; + asciibuf = malloc(bufsize + 1); + if(!asciibuf) { + free(sp); + return GSK_INSUFFICIENT_STORAGE; + } + QadrtConvertE2A(asciibuf, ebcdicbuf, bufsize, bufsize); + asciibuf[bufsize] = '\0'; + sp->ebcdicstr = ebcdicbuf; + sp->asciistr = asciibuf; + sp->next = p->strlist; + p->strlist = sp; + } + *buffer = sp->asciistr; + return GSK_OK; +} + + +int +Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID, + const char * * buffer, int * bufSize) + +{ + struct Curl_gsk_descriptor * p; + int rc; + const char * mybuf; + int mylen; + + if(!my_gsk_handle) + return GSK_INVALID_HANDLE; + if(!buffer || !bufSize) + return GSK_OS400_ERROR_INVALID_POINTER; + p = (struct Curl_gsk_descriptor *) my_gsk_handle; + rc = gsk_attribute_get_buffer(p->h, bufID, &mybuf, &mylen); + if(rc != GSK_OK) + return rc; + rc = cachestring(p, mybuf, mylen, buffer); + if(rc == GSK_OK) + *bufSize = mylen; + return rc; +} + + +int +Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID, + GSK_ENUM_VALUE * enumValue) + +{ + struct Curl_gsk_descriptor * p; + + if(!my_gsk_handle) + return GSK_INVALID_HANDLE; + p = (struct Curl_gsk_descriptor *) my_gsk_handle; + return gsk_attribute_get_enum(p->h, enumID, enumValue); +} + + +int +Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle, + GSK_NUM_ID numID, int * numValue) + +{ + struct Curl_gsk_descriptor * p; + + if(!my_gsk_handle) + return GSK_INVALID_HANDLE; + p = (struct Curl_gsk_descriptor *) my_gsk_handle; + return gsk_attribute_get_numeric_value(p->h, numID, numValue); +} + + +int +Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle, + GSK_CERT_ID certID, + const gsk_cert_data_elem * * certDataElem, + int * certDataElementCount) + +{ + struct Curl_gsk_descriptor * p; + + if(!my_gsk_handle) + return GSK_INVALID_HANDLE; + p = (struct Curl_gsk_descriptor *) my_gsk_handle; + /* No need to convert code: text results are already in ASCII. */ + return gsk_attribute_get_cert_info(p->h, certID, + certDataElem, certDataElementCount); +} + + +int +Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, GSK_MISC_ID miscID) + +{ + struct Curl_gsk_descriptor * p; + + if(!my_session_handle) + return GSK_INVALID_HANDLE; + p = (struct Curl_gsk_descriptor *) my_session_handle; + return gsk_secure_soc_misc(p->h, miscID); +} + + +int +Curl_gsk_secure_soc_read(gsk_handle my_session_handle, char * readBuffer, + int readBufSize, int * amtRead) + +{ + struct Curl_gsk_descriptor * p; + + if(!my_session_handle) + return GSK_INVALID_HANDLE; + p = (struct Curl_gsk_descriptor *) my_session_handle; + return gsk_secure_soc_read(p->h, readBuffer, readBufSize, amtRead); +} + + +int +Curl_gsk_secure_soc_write(gsk_handle my_session_handle, char * writeBuffer, + int writeBufSize, int * amtWritten) + +{ + struct Curl_gsk_descriptor * p; + + if(!my_session_handle) + return GSK_INVALID_HANDLE; + p = (struct Curl_gsk_descriptor *) my_session_handle; + return gsk_secure_soc_write(p->h, writeBuffer, writeBufSize, amtWritten); +} + + +const char * +Curl_gsk_strerror_a(int gsk_return_value) + +{ + return set_thread_string(LK_GSK_ERROR, gsk_strerror(gsk_return_value)); +} + +int +Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle, + int IOCompletionPort, + Qso_OverlappedIO_t * communicationsArea) + +{ + struct Curl_gsk_descriptor * p; + + if(!my_session_handle) + return GSK_INVALID_HANDLE; + p = (struct Curl_gsk_descriptor *) my_session_handle; + return gsk_secure_soc_startInit(p->h, IOCompletionPort, communicationsArea); +} + +#endif /* USE_GSKIT */ + + + +#ifdef HAVE_GSSAPI + +/* ASCII wrappers for the GSSAPI procedures. */ + +static int +Curl_gss_convert_in_place(OM_uint32 * minor_status, gss_buffer_t buf) + +{ + unsigned int i = buf->length; + + /* Convert `buf' in place, from EBCDIC to ASCII. + If error, release the buffer and return -1. Else return 0. */ + + if(i) { + char *t = malloc(i); + if(!t) { + gss_release_buffer(minor_status, buf); + + if(minor_status) + *minor_status = ENOMEM; + + return -1; + } + + QadrtConvertE2A(t, buf->value, i, i); + memcpy(buf->value, t, i); + free(t); + } + + return 0; +} + + +OM_uint32 +Curl_gss_import_name_a(OM_uint32 * minor_status, gss_buffer_t in_name, + gss_OID in_name_type, gss_name_t * out_name) + +{ + int rc; + unsigned int i; + gss_buffer_desc in; + + if(!in_name || !in_name->value || !in_name->length) + return gss_import_name(minor_status, in_name, in_name_type, out_name); + + memcpy((char *) &in, (char *) in_name, sizeof in); + i = in.length; + + in.value = malloc(i + 1); + if(!in.value) { + if(minor_status) + *minor_status = ENOMEM; + + return GSS_S_FAILURE; + } + + QadrtConvertA2E(in.value, in_name->value, i, i); + ((char *) in.value)[i] = '\0'; + rc = gss_import_name(minor_status, &in, in_name_type, out_name); + free(in.value); + return rc; +} + + +OM_uint32 +Curl_gss_display_status_a(OM_uint32 * minor_status, OM_uint32 status_value, + int status_type, gss_OID mech_type, + gss_msg_ctx_t * message_context, gss_buffer_t status_string) + +{ + int rc; + + rc = gss_display_status(minor_status, status_value, status_type, + mech_type, message_context, status_string); + + if(rc != GSS_S_COMPLETE || !status_string || + !status_string->length || !status_string->value) + return rc; + + /* No way to allocate a buffer here, because it will be released by + gss_release_buffer(). The solution is to overwrite the EBCDIC buffer + with ASCII to return it. */ + + if(Curl_gss_convert_in_place(minor_status, status_string)) + return GSS_S_FAILURE; + + return rc; +} + + +OM_uint32 +Curl_gss_init_sec_context_a(OM_uint32 * minor_status, + gss_cred_id_t cred_handle, + gss_ctx_id_t * context_handle, + gss_name_t target_name, gss_OID mech_type, + gss_flags_t req_flags, OM_uint32 time_req, + gss_channel_bindings_t input_chan_bindings, + gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, gss_flags_t * ret_flags, + OM_uint32 * time_rec) + +{ + int rc; + gss_buffer_desc in; + gss_buffer_t inp; + + in.value = NULL; + inp = input_token; + + if(inp) { + if(inp->length && inp->value) { + unsigned int i = inp->length; + + in.value = malloc(i + 1); + if(!in.value) { + if(minor_status) + *minor_status = ENOMEM; + + return GSS_S_FAILURE; + } + + QadrtConvertA2E(in.value, input_token->value, i, i); + ((char *) in.value)[i] = '\0'; + in.length = i; + inp = ∈ + } + } + + rc = gss_init_sec_context(minor_status, cred_handle, context_handle, + target_name, mech_type, req_flags, time_req, + input_chan_bindings, inp, actual_mech_type, + output_token, ret_flags, time_rec); + free(in.value); + + if(rc != GSS_S_COMPLETE || !output_token || + !output_token->length || !output_token->value) + return rc; + + /* No way to allocate a buffer here, because it will be released by + gss_release_buffer(). The solution is to overwrite the EBCDIC buffer + with ASCII to return it. */ + + if(Curl_gss_convert_in_place(minor_status, output_token)) + return GSS_S_FAILURE; + + return rc; +} + + +OM_uint32 +Curl_gss_delete_sec_context_a(OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t output_token) + +{ + int rc; + + rc = gss_delete_sec_context(minor_status, context_handle, output_token); + + if(rc != GSS_S_COMPLETE || !output_token || + !output_token->length || !output_token->value) + return rc; + + /* No way to allocate a buffer here, because it will be released by + gss_release_buffer(). The solution is to overwrite the EBCDIC buffer + with ASCII to return it. */ + + if(Curl_gss_convert_in_place(minor_status, output_token)) + return GSS_S_FAILURE; + + return rc; +} + +#endif /* HAVE_GSSAPI */ + + +#ifndef CURL_DISABLE_LDAP + +/* ASCII wrappers for the LDAP procedures. */ + +void * +Curl_ldap_init_a(char * host, int port) + +{ + unsigned int i; + char * ehost; + void * result; + + if(!host) + return (void *) ldap_init(host, port); + + i = strlen(host); + + ehost = malloc(i + 1); + if(!ehost) + return (void *) NULL; + + QadrtConvertA2E(ehost, host, i, i); + ehost[i] = '\0'; + result = (void *) ldap_init(ehost, port); + free(ehost); + return result; +} + + +int +Curl_ldap_simple_bind_s_a(void * ld, char * dn, char * passwd) + +{ + int i; + char * edn; + char * epasswd; + + edn = (char *) NULL; + epasswd = (char *) NULL; + + if(dn) { + i = strlen(dn); + + edn = malloc(i + 1); + if(!edn) + return LDAP_NO_MEMORY; + + QadrtConvertA2E(edn, dn, i, i); + edn[i] = '\0'; + } + + if(passwd) { + i = strlen(passwd); + + epasswd = malloc(i + 1); + if(!epasswd) { + free(edn); + return LDAP_NO_MEMORY; + } + + QadrtConvertA2E(epasswd, passwd, i, i); + epasswd[i] = '\0'; + } + + i = ldap_simple_bind_s(ld, edn, epasswd); + free(epasswd); + free(edn); + return i; +} + + +int +Curl_ldap_search_s_a(void * ld, char * base, int scope, char * filter, + char * * attrs, int attrsonly, LDAPMessage * * res) + +{ + int i; + int j; + char * ebase; + char * efilter; + char * * eattrs; + int status; + + ebase = (char *) NULL; + efilter = (char *) NULL; + eattrs = (char * *) NULL; + status = LDAP_SUCCESS; + + if(base) { + i = strlen(base); + + ebase = malloc(i + 1); + if(!ebase) + status = LDAP_NO_MEMORY; + else { + QadrtConvertA2E(ebase, base, i, i); + ebase[i] = '\0'; + } + } + + if(filter && status == LDAP_SUCCESS) { + i = strlen(filter); + + efilter = malloc(i + 1); + if(!efilter) + status = LDAP_NO_MEMORY; + else { + QadrtConvertA2E(efilter, filter, i, i); + efilter[i] = '\0'; + } + } + + if(attrs && status == LDAP_SUCCESS) { + for(i = 0; attrs[i++];) + ; + + eattrs = calloc(i, sizeof *eattrs); + if(!eattrs) + status = LDAP_NO_MEMORY; + else { + for(j = 0; attrs[j]; j++) { + i = strlen(attrs[j]); + + eattrs[j] = malloc(i + 1); + if(!eattrs[j]) { + status = LDAP_NO_MEMORY; + break; + } + + QadrtConvertA2E(eattrs[j], attrs[j], i, i); + eattrs[j][i] = '\0'; + } + } + } + + if(status == LDAP_SUCCESS) + status = ldap_search_s(ld, ebase? ebase: "", scope, + efilter? efilter: "(objectclass=*)", + eattrs, attrsonly, res); + + if(eattrs) { + for(j = 0; eattrs[j]; j++) + free(eattrs[j]); + + free(eattrs); + } + + free(efilter); + free(ebase); + return status; +} + + +struct berval * * +Curl_ldap_get_values_len_a(void * ld, LDAPMessage * entry, const char * attr) + +{ + char * cp; + struct berval * * result; + + cp = (char *) NULL; + + if(attr) { + int i = strlen(attr); + + cp = malloc(i + 1); + if(!cp) { + ldap_set_lderrno(ld, LDAP_NO_MEMORY, NULL, + ldap_err2string(LDAP_NO_MEMORY)); + return (struct berval * *) NULL; + } + + QadrtConvertA2E(cp, attr, i, i); + cp[i] = '\0'; + } + + result = ldap_get_values_len(ld, entry, cp); + free(cp); + + /* Result data are binary in nature, so they haven't been + converted to EBCDIC. Therefore do not convert. */ + + return result; +} + + +char * +Curl_ldap_err2string_a(int error) + +{ + return set_thread_string(LK_LDAP_ERROR, ldap_err2string(error)); +} + + +char * +Curl_ldap_get_dn_a(void * ld, LDAPMessage * entry) + +{ + int i; + char * cp; + char * cp2; + + cp = ldap_get_dn(ld, entry); + + if(!cp) + return cp; + + i = strlen(cp); + + cp2 = malloc(i + 1); + if(!cp2) + return cp2; + + QadrtConvertE2A(cp2, cp, i, i); + cp2[i] = '\0'; + + /* No way to allocate a buffer here, because it will be released by + ldap_memfree() and ldap_memalloc() does not exist. The solution is to + overwrite the EBCDIC buffer with ASCII to return it. */ + + strcpy(cp, cp2); + free(cp2); + return cp; +} + + +char * +Curl_ldap_first_attribute_a(void * ld, + LDAPMessage * entry, BerElement * * berptr) + +{ + int i; + char * cp; + char * cp2; + + cp = ldap_first_attribute(ld, entry, berptr); + + if(!cp) + return cp; + + i = strlen(cp); + + cp2 = malloc(i + 1); + if(!cp2) + return cp2; + + QadrtConvertE2A(cp2, cp, i, i); + cp2[i] = '\0'; + + /* No way to allocate a buffer here, because it will be released by + ldap_memfree() and ldap_memalloc() does not exist. The solution is to + overwrite the EBCDIC buffer with ASCII to return it. */ + + strcpy(cp, cp2); + free(cp2); + return cp; +} + + +char * +Curl_ldap_next_attribute_a(void * ld, + LDAPMessage * entry, BerElement * berptr) + +{ + int i; + char * cp; + char * cp2; + + cp = ldap_next_attribute(ld, entry, berptr); + + if(!cp) + return cp; + + i = strlen(cp); + + cp2 = malloc(i + 1); + if(!cp2) + return cp2; + + QadrtConvertE2A(cp2, cp, i, i); + cp2[i] = '\0'; + + /* No way to allocate a buffer here, because it will be released by + ldap_memfree() and ldap_memalloc() does not exist. The solution is to + overwrite the EBCDIC buffer with ASCII to return it. */ + + strcpy(cp, cp2); + free(cp2); + return cp; +} + +#endif /* CURL_DISABLE_LDAP */ + + +static int +convert_sockaddr(struct sockaddr_storage * dstaddr, + const struct sockaddr * srcaddr, int srclen) + +{ + const struct sockaddr_un * srcu; + struct sockaddr_un * dstu; + unsigned int i; + unsigned int dstsize; + + /* Convert a socket address into job CCSID, if needed. */ + + if(!srcaddr || srclen < offsetof(struct sockaddr, sa_family) + + sizeof srcaddr->sa_family || srclen > sizeof *dstaddr) { + errno = EINVAL; + return -1; + } + + memcpy((char *) dstaddr, (char *) srcaddr, srclen); + + switch (srcaddr->sa_family) { + + case AF_UNIX: + srcu = (const struct sockaddr_un *) srcaddr; + dstu = (struct sockaddr_un *) dstaddr; + dstsize = sizeof *dstaddr - offsetof(struct sockaddr_un, sun_path); + srclen -= offsetof(struct sockaddr_un, sun_path); + i = QadrtConvertA2E(dstu->sun_path, srcu->sun_path, dstsize - 1, srclen); + dstu->sun_path[i] = '\0'; + i += offsetof(struct sockaddr_un, sun_path); + srclen = i; + } + + return srclen; +} + + +int +Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen) + +{ + int i; + struct sockaddr_storage laddr; + + i = convert_sockaddr(&laddr, destaddr, addrlen); + + if(i < 0) + return -1; + + return connect(sd, (struct sockaddr *) &laddr, i); +} + + +int +Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen) + +{ + int i; + struct sockaddr_storage laddr; + + i = convert_sockaddr(&laddr, localaddr, addrlen); + + if(i < 0) + return -1; + + return bind(sd, (struct sockaddr *) &laddr, i); +} + + +int +Curl_os400_sendto(int sd, char * buffer, int buflen, int flags, + struct sockaddr * dstaddr, int addrlen) + +{ + int i; + struct sockaddr_storage laddr; + + i = convert_sockaddr(&laddr, dstaddr, addrlen); + + if(i < 0) + return -1; + + return sendto(sd, buffer, buflen, flags, (struct sockaddr *) &laddr, i); +} + + +int +Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags, + struct sockaddr * fromaddr, int * addrlen) + +{ + int i; + int rcvlen; + int laddrlen; + const struct sockaddr_un * srcu; + struct sockaddr_un * dstu; + struct sockaddr_storage laddr; + + if(!fromaddr || !addrlen || *addrlen <= 0) + return recvfrom(sd, buffer, buflen, flags, fromaddr, addrlen); + + laddrlen = sizeof laddr; + laddr.ss_family = AF_UNSPEC; /* To detect if unused. */ + rcvlen = recvfrom(sd, buffer, buflen, flags, + (struct sockaddr *) &laddr, &laddrlen); + + if(rcvlen < 0) + return rcvlen; + + switch (laddr.ss_family) { + + case AF_UNIX: + srcu = (const struct sockaddr_un *) &laddr; + dstu = (struct sockaddr_un *) fromaddr; + i = *addrlen - offsetof(struct sockaddr_un, sun_path); + laddrlen -= offsetof(struct sockaddr_un, sun_path); + i = QadrtConvertE2A(dstu->sun_path, srcu->sun_path, i, laddrlen); + laddrlen = i + offsetof(struct sockaddr_un, sun_path); + + if(laddrlen < *addrlen) + dstu->sun_path[i] = '\0'; + + break; + + case AF_UNSPEC: + break; + + default: + if(laddrlen > *addrlen) + laddrlen = *addrlen; + + if(laddrlen) + memcpy((char *) fromaddr, (char *) &laddr, laddrlen); + + break; + } + + *addrlen = laddrlen; + return rcvlen; +} + + +#ifdef HAVE_LIBZ +const char * +Curl_os400_zlibVersion(void) + +{ + return set_thread_string(LK_ZLIB_VERSION, zlibVersion()); +} + + +int +Curl_os400_inflateInit_(z_streamp strm, const char * version, int stream_size) + +{ + z_const char * msgb4 = strm->msg; + int ret; + + ret = inflateInit(strm); + + if(strm->msg != msgb4) + strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); + + return ret; +} + + +int +Curl_os400_inflateInit2_(z_streamp strm, int windowBits, + const char * version, int stream_size) + +{ + z_const char * msgb4 = strm->msg; + int ret; + + ret = inflateInit2(strm, windowBits); + + if(strm->msg != msgb4) + strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); + + return ret; +} + + +int +Curl_os400_inflate(z_streamp strm, int flush) + +{ + z_const char * msgb4 = strm->msg; + int ret; + + ret = inflate(strm, flush); + + if(strm->msg != msgb4) + strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); + + return ret; +} + + +int +Curl_os400_inflateEnd(z_streamp strm) + +{ + z_const char * msgb4 = strm->msg; + int ret; + + ret = inflateEnd(strm); + + if(strm->msg != msgb4) + strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); + + return ret; +} + +#endif
