Annotation of embedaddon/curl/packages/OS400/os400sys.c, revision 1.1

1.1     ! misho       1: /***************************************************************************
        !             2:  *                                  _   _ ____  _
        !             3:  *  Project                     ___| | | |  _ \| |
        !             4:  *                             / __| | | | |_) | |
        !             5:  *                            | (__| |_| |  _ <| |___
        !             6:  *                             \___|\___/|_| \_\_____|
        !             7:  *
        !             8:  * Copyright (C) 1998 - 2019, 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.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: 
        !            24: /* OS/400 additional support. */
        !            25: 
        !            26: #include <curl/curl.h>
        !            27: #include "config-os400.h"  /* Not curl_setup.h: we only need some defines. */
        !            28: 
        !            29: #include <sys/types.h>
        !            30: #include <sys/socket.h>
        !            31: #include <sys/un.h>
        !            32: 
        !            33: #include <stdlib.h>
        !            34: #include <stddef.h>
        !            35: #include <string.h>
        !            36: #include <pthread.h>
        !            37: #include <netdb.h>
        !            38: #include <qadrt.h>
        !            39: #include <errno.h>
        !            40: 
        !            41: #ifdef HAVE_ZLIB_H
        !            42: #include <zlib.h>
        !            43: #endif
        !            44: 
        !            45: #ifdef USE_GSKIT
        !            46: #include <gskssl.h>
        !            47: #include <qsoasync.h>
        !            48: #endif
        !            49: 
        !            50: #ifdef HAVE_GSSAPI
        !            51: #include <gssapi.h>
        !            52: #endif
        !            53: 
        !            54: #ifndef CURL_DISABLE_LDAP
        !            55: #include <ldap.h>
        !            56: #endif
        !            57: 
        !            58: #include <netinet/in.h>
        !            59: #include <arpa/inet.h>
        !            60: 
        !            61: #include "os400sys.h"
        !            62: 
        !            63: 
        !            64: /**
        !            65: ***     QADRT OS/400 ASCII runtime defines only the most used procedures, but
        !            66: ***             but a lot of them are not supported. This module implements
        !            67: ***             ASCII wrappers for those that are used by libcurl, but not
        !            68: ***             defined by QADRT.
        !            69: **/
        !            70: 
        !            71: #pragma convert(0)                              /* Restore EBCDIC. */
        !            72: 
        !            73: 
        !            74: #define MIN_BYTE_GAIN   1024    /* Minimum gain when shortening a buffer. */
        !            75: 
        !            76: typedef struct {
        !            77:         unsigned long   size;                   /* Buffer size. */
        !            78:         char *          buf;                    /* Buffer address. */
        !            79: }               buffer_t;
        !            80: 
        !            81: 
        !            82: static char *   buffer_undef(localkey_t key, long size);
        !            83: static char *   buffer_threaded(localkey_t key, long size);
        !            84: static char *   buffer_unthreaded(localkey_t key, long size);
        !            85: 
        !            86: static pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;
        !            87: static pthread_key_t    thdkey;
        !            88: static buffer_t *       locbufs;
        !            89: 
        !            90: char *  (* Curl_thread_buffer)(localkey_t key, long size) = buffer_undef;
        !            91: 
        !            92: 
        !            93: static void
        !            94: thdbufdestroy(void * private)
        !            95: 
        !            96: {
        !            97:   if(private) {
        !            98:     buffer_t * p = (buffer_t *) private;
        !            99:     localkey_t i;
        !           100: 
        !           101:     for(i = (localkey_t) 0; i < LK_LAST; i++) {
        !           102:       free(p->buf);
        !           103:       p++;
        !           104:       }
        !           105: 
        !           106:     free(private);
        !           107:     }
        !           108: }
        !           109: 
        !           110: 
        !           111: static void
        !           112: terminate(void)
        !           113: 
        !           114: {
        !           115:   if(Curl_thread_buffer == buffer_threaded) {
        !           116:     locbufs = pthread_getspecific(thdkey);
        !           117:     pthread_setspecific(thdkey, (void *) NULL);
        !           118:     pthread_key_delete(thdkey);
        !           119:     }
        !           120: 
        !           121:   if(Curl_thread_buffer != buffer_undef) {
        !           122:     thdbufdestroy((void *) locbufs);
        !           123:     locbufs = (buffer_t *) NULL;
        !           124:     }
        !           125: 
        !           126:   Curl_thread_buffer = buffer_undef;
        !           127: }
        !           128: 
        !           129: 
        !           130: static char *
        !           131: get_buffer(buffer_t * buf, long size)
        !           132: 
        !           133: {
        !           134:   char * cp;
        !           135: 
        !           136:   /* If `size' >= 0, make sure buffer at `buf' is at least `size'-byte long.
        !           137:      Return the buffer address. */
        !           138: 
        !           139:   if(size < 0)
        !           140:     return buf->buf;
        !           141: 
        !           142:   if(!buf->buf) {
        !           143:     buf->buf = malloc(size);
        !           144:     if(buf->buf)
        !           145:       buf->size = size;
        !           146: 
        !           147:     return buf->buf;
        !           148:   }
        !           149: 
        !           150:   if((unsigned long) size <= buf->size) {
        !           151:     /* Shorten the buffer only if it frees a significant byte count. This
        !           152:        avoids some realloc() overhead. */
        !           153: 
        !           154:     if(buf->size - size < MIN_BYTE_GAIN)
        !           155:       return buf->buf;
        !           156:   }
        !           157: 
        !           158:   /* Resize the buffer. */
        !           159: 
        !           160:   cp = realloc(buf->buf, size);
        !           161:   if(cp) {
        !           162:     buf->buf = cp;
        !           163:     buf->size = size;
        !           164:   }
        !           165:   else if(size <= buf->size)
        !           166:     cp = buf->buf;
        !           167: 
        !           168:   return cp;
        !           169: }
        !           170: 
        !           171: 
        !           172: static char *
        !           173: buffer_unthreaded(localkey_t key, long size)
        !           174: 
        !           175: {
        !           176:   return get_buffer(locbufs + key, size);
        !           177: }
        !           178: 
        !           179: 
        !           180: static char *
        !           181: buffer_threaded(localkey_t key, long size)
        !           182: 
        !           183: {
        !           184:   buffer_t * bufs;
        !           185: 
        !           186:   /* Get the buffer for the given local key in the current thread, and
        !           187:      make sure it is at least `size'-byte long. Set `size' to < 0 to get
        !           188:      its address only. */
        !           189: 
        !           190:   bufs = (buffer_t *) pthread_getspecific(thdkey);
        !           191: 
        !           192:   if(!bufs) {
        !           193:     if(size < 0)
        !           194:       return (char *) NULL;             /* No buffer yet. */
        !           195: 
        !           196:     /* Allocate buffer descriptors for the current thread. */
        !           197: 
        !           198:     bufs = calloc((size_t) LK_LAST, sizeof(*bufs));
        !           199:     if(!bufs)
        !           200:       return (char *) NULL;
        !           201: 
        !           202:     if(pthread_setspecific(thdkey, (void *) bufs)) {
        !           203:       free(bufs);
        !           204:       return (char *) NULL;
        !           205:     }
        !           206:   }
        !           207: 
        !           208:   return get_buffer(bufs + key, size);
        !           209: }
        !           210: 
        !           211: 
        !           212: static char *
        !           213: buffer_undef(localkey_t key, long size)
        !           214: 
        !           215: {
        !           216:   /* Define the buffer system, get the buffer for the given local key in
        !           217:      the current thread, and make sure it is at least `size'-byte long.
        !           218:      Set `size' to < 0 to get its address only. */
        !           219: 
        !           220:   pthread_mutex_lock(&mutex);
        !           221: 
        !           222:   /* Determine if we can use pthread-specific data. */
        !           223: 
        !           224:   if(Curl_thread_buffer == buffer_undef) {      /* If unchanged during lock. */
        !           225:     if(!pthread_key_create(&thdkey, thdbufdestroy))
        !           226:       Curl_thread_buffer = buffer_threaded;
        !           227:     else if(!(locbufs = calloc((size_t) LK_LAST, sizeof(*locbufs)))) {
        !           228:       pthread_mutex_unlock(&mutex);
        !           229:       return (char *) NULL;
        !           230:       }
        !           231:     else
        !           232:         Curl_thread_buffer = buffer_unthreaded;
        !           233: 
        !           234:     atexit(terminate);
        !           235:     }
        !           236: 
        !           237:   pthread_mutex_unlock(&mutex);
        !           238:   return Curl_thread_buffer(key, size);
        !           239: }
        !           240: 
        !           241: 
        !           242: static char *
        !           243: set_thread_string(localkey_t key, const char * s)
        !           244: 
        !           245: {
        !           246:   int i;
        !           247:   char * cp;
        !           248: 
        !           249:   if(!s)
        !           250:     return (char *) NULL;
        !           251: 
        !           252:   i = strlen(s) + 1;
        !           253:   cp = Curl_thread_buffer(key, MAX_CONV_EXPANSION * i + 1);
        !           254: 
        !           255:   if(cp) {
        !           256:     i = QadrtConvertE2A(cp, s, MAX_CONV_EXPANSION * i, i);
        !           257:     cp[i] = '\0';
        !           258:   }
        !           259: 
        !           260:   return cp;
        !           261: }
        !           262: 
        !           263: 
        !           264: int
        !           265: Curl_getnameinfo_a(const struct sockaddr * sa, curl_socklen_t salen,
        !           266:               char * nodename, curl_socklen_t nodenamelen,
        !           267:               char * servname, curl_socklen_t servnamelen,
        !           268:               int flags)
        !           269: 
        !           270: {
        !           271:   char *enodename = NULL;
        !           272:   char *eservname = NULL;
        !           273:   int status;
        !           274: 
        !           275:   if(nodename && nodenamelen) {
        !           276:     enodename = malloc(nodenamelen);
        !           277:     if(!enodename)
        !           278:       return EAI_MEMORY;
        !           279:   }
        !           280: 
        !           281:   if(servname && servnamelen) {
        !           282:     eservname = malloc(servnamelen);
        !           283:     if(!eservname) {
        !           284:       free(enodename);
        !           285:       return EAI_MEMORY;
        !           286:     }
        !           287:   }
        !           288: 
        !           289:   status = getnameinfo(sa, salen, enodename, nodenamelen,
        !           290:                        eservname, servnamelen, flags);
        !           291: 
        !           292:   if(!status) {
        !           293:     int i;
        !           294:     if(enodename) {
        !           295:       i = QadrtConvertE2A(nodename, enodename,
        !           296:         nodenamelen - 1, strlen(enodename));
        !           297:       nodename[i] = '\0';
        !           298:       }
        !           299: 
        !           300:     if(eservname) {
        !           301:       i = QadrtConvertE2A(servname, eservname,
        !           302:         servnamelen - 1, strlen(eservname));
        !           303:       servname[i] = '\0';
        !           304:       }
        !           305:     }
        !           306: 
        !           307:   free(enodename);
        !           308:   free(eservname);
        !           309:   return status;
        !           310: }
        !           311: 
        !           312: 
        !           313: int
        !           314: Curl_getaddrinfo_a(const char * nodename, const char * servname,
        !           315:             const struct addrinfo * hints,
        !           316:             struct addrinfo * * res)
        !           317: 
        !           318: {
        !           319:   char * enodename;
        !           320:   char * eservname;
        !           321:   int status;
        !           322:   int i;
        !           323: 
        !           324:   enodename = (char *) NULL;
        !           325:   eservname = (char *) NULL;
        !           326: 
        !           327:   if(nodename) {
        !           328:     i = strlen(nodename);
        !           329: 
        !           330:     enodename = malloc(i + 1);
        !           331:     if(!enodename)
        !           332:       return EAI_MEMORY;
        !           333: 
        !           334:     i = QadrtConvertA2E(enodename, nodename, i, i);
        !           335:     enodename[i] = '\0';
        !           336:   }
        !           337: 
        !           338:   if(servname) {
        !           339:     i = strlen(servname);
        !           340: 
        !           341:     eservname = malloc(i + 1);
        !           342:     if(!eservname) {
        !           343:       free(enodename);
        !           344:       return EAI_MEMORY;
        !           345:     }
        !           346: 
        !           347:     QadrtConvertA2E(eservname, servname, i, i);
        !           348:     eservname[i] = '\0';
        !           349:   }
        !           350: 
        !           351:   status = getaddrinfo(enodename, eservname, hints, res);
        !           352:   free(enodename);
        !           353:   free(eservname);
        !           354:   return status;
        !           355: }
        !           356: 
        !           357: 
        !           358: #ifdef USE_GSKIT
        !           359: 
        !           360: /* ASCII wrappers for the GSKit procedures. */
        !           361: 
        !           362: /*
        !           363:  * EBCDIC --> ASCII string mapping table.
        !           364:  * Some strings returned by GSKit are dynamically allocated and automatically
        !           365:  * released when closing the handle.
        !           366:  * To provide the same functionality, we use a "private" handle that
        !           367:  * holds the GSKit handle and a list of string mappings. This will allow
        !           368:  * avoid conversion of already converted strings and releasing them upon
        !           369:  * close time.
        !           370:  */
        !           371: 
        !           372: struct gskstrlist {
        !           373:   struct gskstrlist * next;
        !           374:   const char * ebcdicstr;
        !           375:   const char * asciistr;
        !           376: };
        !           377: 
        !           378: struct Curl_gsk_descriptor {
        !           379:   gsk_handle h;
        !           380:   struct gskstrlist * strlist;
        !           381: };
        !           382: 
        !           383: 
        !           384: int
        !           385: Curl_gsk_environment_open(gsk_handle * my_env_handle)
        !           386: 
        !           387: {
        !           388:   struct Curl_gsk_descriptor * p;
        !           389:   int rc;
        !           390: 
        !           391:   if(!my_env_handle)
        !           392:     return GSK_OS400_ERROR_INVALID_POINTER;
        !           393:   p = (struct Curl_gsk_descriptor *) malloc(sizeof(*p));
        !           394:   if(!p)
        !           395:     return GSK_INSUFFICIENT_STORAGE;
        !           396:   p->strlist = (struct gskstrlist *) NULL;
        !           397:   rc = gsk_environment_open(&p->h);
        !           398:   if(rc != GSK_OK)
        !           399:     free(p);
        !           400:   else
        !           401:     *my_env_handle = (gsk_handle) p;
        !           402:   return rc;
        !           403: }
        !           404: 
        !           405: 
        !           406: int
        !           407: Curl_gsk_secure_soc_open(gsk_handle my_env_handle,
        !           408:                          gsk_handle * my_session_handle)
        !           409: 
        !           410: {
        !           411:   struct Curl_gsk_descriptor * p;
        !           412:   gsk_handle h;
        !           413:   int rc;
        !           414: 
        !           415:   if(!my_env_handle)
        !           416:     return GSK_INVALID_HANDLE;
        !           417:   if(!my_session_handle)
        !           418:     return GSK_OS400_ERROR_INVALID_POINTER;
        !           419:   h = ((struct Curl_gsk_descriptor *) my_env_handle)->h;
        !           420:   p = (struct Curl_gsk_descriptor *) malloc(sizeof(*p));
        !           421:   if(!p)
        !           422:     return GSK_INSUFFICIENT_STORAGE;
        !           423:   p->strlist = (struct gskstrlist *) NULL;
        !           424:   rc = gsk_secure_soc_open(h, &p->h);
        !           425:   if(rc != GSK_OK)
        !           426:     free(p);
        !           427:   else
        !           428:     *my_session_handle = (gsk_handle) p;
        !           429:   return rc;
        !           430: }
        !           431: 
        !           432: 
        !           433: static void
        !           434: gsk_free_handle(struct Curl_gsk_descriptor * p)
        !           435: 
        !           436: {
        !           437:   struct gskstrlist * q;
        !           438: 
        !           439:   while((q = p->strlist)) {
        !           440:     p->strlist = q;
        !           441:     free((void *) q->asciistr);
        !           442:     free(q);
        !           443:   }
        !           444:   free(p);
        !           445: }
        !           446: 
        !           447: 
        !           448: int
        !           449: Curl_gsk_environment_close(gsk_handle * my_env_handle)
        !           450: 
        !           451: {
        !           452:   struct Curl_gsk_descriptor * p;
        !           453:   int rc;
        !           454: 
        !           455:   if(!my_env_handle)
        !           456:     return GSK_OS400_ERROR_INVALID_POINTER;
        !           457:   if(!*my_env_handle)
        !           458:     return GSK_INVALID_HANDLE;
        !           459:   p = (struct Curl_gsk_descriptor *) *my_env_handle;
        !           460:   rc = gsk_environment_close(&p->h);
        !           461:   if(rc == GSK_OK) {
        !           462:     gsk_free_handle(p);
        !           463:     *my_env_handle = (gsk_handle) NULL;
        !           464:   }
        !           465:   return rc;
        !           466: }
        !           467: 
        !           468: 
        !           469: int
        !           470: Curl_gsk_secure_soc_close(gsk_handle * my_session_handle)
        !           471: 
        !           472: {
        !           473:   struct Curl_gsk_descriptor * p;
        !           474:   int rc;
        !           475: 
        !           476:   if(!my_session_handle)
        !           477:     return GSK_OS400_ERROR_INVALID_POINTER;
        !           478:   if(!*my_session_handle)
        !           479:     return GSK_INVALID_HANDLE;
        !           480:   p = (struct Curl_gsk_descriptor *) *my_session_handle;
        !           481:   rc = gsk_secure_soc_close(&p->h);
        !           482:   if(rc == GSK_OK) {
        !           483:     gsk_free_handle(p);
        !           484:     *my_session_handle = (gsk_handle) NULL;
        !           485:   }
        !           486:   return rc;
        !           487: }
        !           488: 
        !           489: 
        !           490: int
        !           491: Curl_gsk_environment_init(gsk_handle my_env_handle)
        !           492: 
        !           493: {
        !           494:   struct Curl_gsk_descriptor * p;
        !           495: 
        !           496:   if(!my_env_handle)
        !           497:     return GSK_INVALID_HANDLE;
        !           498:   p = (struct Curl_gsk_descriptor *) my_env_handle;
        !           499:   return gsk_environment_init(p->h);
        !           500: }
        !           501: 
        !           502: 
        !           503: int
        !           504: Curl_gsk_secure_soc_init(gsk_handle my_session_handle)
        !           505: 
        !           506: {
        !           507:   struct Curl_gsk_descriptor * p;
        !           508: 
        !           509:   if(!my_session_handle)
        !           510:     return GSK_INVALID_HANDLE;
        !           511:   p = (struct Curl_gsk_descriptor *) my_session_handle;
        !           512:   return gsk_secure_soc_init(p->h);
        !           513: }
        !           514: 
        !           515: 
        !           516: int
        !           517: Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID,
        !           518:                                 const char * buffer, int bufSize)
        !           519: 
        !           520: {
        !           521:   struct Curl_gsk_descriptor * p;
        !           522:   char * ebcdicbuf;
        !           523:   int rc;
        !           524: 
        !           525:   if(!my_gsk_handle)
        !           526:     return GSK_INVALID_HANDLE;
        !           527:   if(!buffer)
        !           528:     return GSK_OS400_ERROR_INVALID_POINTER;
        !           529:   if(bufSize < 0)
        !           530:     return GSK_ATTRIBUTE_INVALID_LENGTH;
        !           531:   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
        !           532:   if(!bufSize)
        !           533:     bufSize = strlen(buffer);
        !           534:   ebcdicbuf = malloc(bufSize + 1);
        !           535:   if(!ebcdicbuf)
        !           536:     return GSK_INSUFFICIENT_STORAGE;
        !           537:   QadrtConvertA2E(ebcdicbuf, buffer, bufSize, bufSize);
        !           538:   ebcdicbuf[bufSize] = '\0';
        !           539:   rc = gsk_attribute_set_buffer(p->h, bufID, ebcdicbuf, bufSize);
        !           540:   free(ebcdicbuf);
        !           541:   return rc;
        !           542: }
        !           543: 
        !           544: 
        !           545: int
        !           546: Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID,
        !           547:                             GSK_ENUM_VALUE enumValue)
        !           548: 
        !           549: {
        !           550:   struct Curl_gsk_descriptor * p;
        !           551: 
        !           552:   if(!my_gsk_handle)
        !           553:     return GSK_INVALID_HANDLE;
        !           554:   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
        !           555:   return gsk_attribute_set_enum(p->h, enumID, enumValue);
        !           556: }
        !           557: 
        !           558: 
        !           559: int
        !           560: Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
        !           561:                                      GSK_NUM_ID numID, int numValue)
        !           562: 
        !           563: {
        !           564:   struct Curl_gsk_descriptor * p;
        !           565: 
        !           566:   if(!my_gsk_handle)
        !           567:     return GSK_INVALID_HANDLE;
        !           568:   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
        !           569:   return gsk_attribute_set_numeric_value(p->h, numID, numValue);
        !           570: }
        !           571: 
        !           572: 
        !           573: int
        !           574: Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
        !           575:                                 GSK_CALLBACK_ID callBackID,
        !           576:                                 void * callBackAreaPtr)
        !           577: 
        !           578: {
        !           579:   struct Curl_gsk_descriptor * p;
        !           580: 
        !           581:   if(!my_gsk_handle)
        !           582:     return GSK_INVALID_HANDLE;
        !           583:   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
        !           584:   return gsk_attribute_set_callback(p->h, callBackID, callBackAreaPtr);
        !           585: }
        !           586: 
        !           587: 
        !           588: static int
        !           589: cachestring(struct Curl_gsk_descriptor * p,
        !           590:             const char * ebcdicbuf, int bufsize, const char * * buffer)
        !           591: 
        !           592: {
        !           593:   int rc;
        !           594:   char * asciibuf;
        !           595:   struct gskstrlist * sp;
        !           596: 
        !           597:   for(sp = p->strlist; sp; sp = sp->next)
        !           598:     if(sp->ebcdicstr == ebcdicbuf)
        !           599:       break;
        !           600:   if(!sp) {
        !           601:     sp = (struct gskstrlist *) malloc(sizeof(*sp));
        !           602:     if(!sp)
        !           603:       return GSK_INSUFFICIENT_STORAGE;
        !           604:     asciibuf = malloc(bufsize + 1);
        !           605:     if(!asciibuf) {
        !           606:       free(sp);
        !           607:       return GSK_INSUFFICIENT_STORAGE;
        !           608:     }
        !           609:     QadrtConvertE2A(asciibuf, ebcdicbuf, bufsize, bufsize);
        !           610:     asciibuf[bufsize] = '\0';
        !           611:     sp->ebcdicstr = ebcdicbuf;
        !           612:     sp->asciistr = asciibuf;
        !           613:     sp->next = p->strlist;
        !           614:     p->strlist = sp;
        !           615:   }
        !           616:   *buffer = sp->asciistr;
        !           617:   return GSK_OK;
        !           618: }
        !           619: 
        !           620: 
        !           621: int
        !           622: Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID,
        !           623:                                 const char * * buffer, int * bufSize)
        !           624: 
        !           625: {
        !           626:   struct Curl_gsk_descriptor * p;
        !           627:   int rc;
        !           628:   const char * mybuf;
        !           629:   int mylen;
        !           630: 
        !           631:   if(!my_gsk_handle)
        !           632:     return GSK_INVALID_HANDLE;
        !           633:   if(!buffer || !bufSize)
        !           634:     return GSK_OS400_ERROR_INVALID_POINTER;
        !           635:   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
        !           636:   rc = gsk_attribute_get_buffer(p->h, bufID, &mybuf, &mylen);
        !           637:   if(rc != GSK_OK)
        !           638:     return rc;
        !           639:   rc = cachestring(p, mybuf, mylen, buffer);
        !           640:   if(rc == GSK_OK)
        !           641:     *bufSize = mylen;
        !           642:   return rc;
        !           643: }
        !           644: 
        !           645: 
        !           646: int
        !           647: Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID,
        !           648:                             GSK_ENUM_VALUE * enumValue)
        !           649: 
        !           650: {
        !           651:   struct Curl_gsk_descriptor * p;
        !           652: 
        !           653:   if(!my_gsk_handle)
        !           654:     return GSK_INVALID_HANDLE;
        !           655:   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
        !           656:   return gsk_attribute_get_enum(p->h, enumID, enumValue);
        !           657: }
        !           658: 
        !           659: 
        !           660: int
        !           661: Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
        !           662:                                      GSK_NUM_ID numID, int * numValue)
        !           663: 
        !           664: {
        !           665:   struct Curl_gsk_descriptor * p;
        !           666: 
        !           667:   if(!my_gsk_handle)
        !           668:     return GSK_INVALID_HANDLE;
        !           669:   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
        !           670:   return gsk_attribute_get_numeric_value(p->h, numID, numValue);
        !           671: }
        !           672: 
        !           673: 
        !           674: int
        !           675: Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
        !           676:                                  GSK_CERT_ID certID,
        !           677:                                  const gsk_cert_data_elem * * certDataElem,
        !           678:                                  int * certDataElementCount)
        !           679: 
        !           680: {
        !           681:   struct Curl_gsk_descriptor * p;
        !           682: 
        !           683:   if(!my_gsk_handle)
        !           684:     return GSK_INVALID_HANDLE;
        !           685:   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
        !           686:   /* No need to convert code: text results are already in ASCII. */
        !           687:   return gsk_attribute_get_cert_info(p->h, certID,
        !           688:                                      certDataElem, certDataElementCount);
        !           689: }
        !           690: 
        !           691: 
        !           692: int
        !           693: Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, GSK_MISC_ID miscID)
        !           694: 
        !           695: {
        !           696:   struct Curl_gsk_descriptor * p;
        !           697: 
        !           698:   if(!my_session_handle)
        !           699:     return GSK_INVALID_HANDLE;
        !           700:   p = (struct Curl_gsk_descriptor *) my_session_handle;
        !           701:   return gsk_secure_soc_misc(p->h, miscID);
        !           702: }
        !           703: 
        !           704: 
        !           705: int
        !           706: Curl_gsk_secure_soc_read(gsk_handle my_session_handle, char * readBuffer,
        !           707:                          int readBufSize, int * amtRead)
        !           708: 
        !           709: {
        !           710:   struct Curl_gsk_descriptor * p;
        !           711: 
        !           712:   if(!my_session_handle)
        !           713:     return GSK_INVALID_HANDLE;
        !           714:   p = (struct Curl_gsk_descriptor *) my_session_handle;
        !           715:   return gsk_secure_soc_read(p->h, readBuffer, readBufSize, amtRead);
        !           716: }
        !           717: 
        !           718: 
        !           719: int
        !           720: Curl_gsk_secure_soc_write(gsk_handle my_session_handle, char * writeBuffer,
        !           721:                           int writeBufSize, int * amtWritten)
        !           722: 
        !           723: {
        !           724:   struct Curl_gsk_descriptor * p;
        !           725: 
        !           726:   if(!my_session_handle)
        !           727:     return GSK_INVALID_HANDLE;
        !           728:   p = (struct Curl_gsk_descriptor *) my_session_handle;
        !           729:   return gsk_secure_soc_write(p->h, writeBuffer, writeBufSize, amtWritten);
        !           730: }
        !           731: 
        !           732: 
        !           733: const char *
        !           734: Curl_gsk_strerror_a(int gsk_return_value)
        !           735: 
        !           736: {
        !           737:   return set_thread_string(LK_GSK_ERROR, gsk_strerror(gsk_return_value));
        !           738: }
        !           739: 
        !           740: int
        !           741: Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle,
        !           742:                               int IOCompletionPort,
        !           743:                               Qso_OverlappedIO_t * communicationsArea)
        !           744: 
        !           745: {
        !           746:   struct Curl_gsk_descriptor * p;
        !           747: 
        !           748:   if(!my_session_handle)
        !           749:     return GSK_INVALID_HANDLE;
        !           750:   p = (struct Curl_gsk_descriptor *) my_session_handle;
        !           751:   return gsk_secure_soc_startInit(p->h, IOCompletionPort, communicationsArea);
        !           752: }
        !           753: 
        !           754: #endif /* USE_GSKIT */
        !           755: 
        !           756: 
        !           757: 
        !           758: #ifdef HAVE_GSSAPI
        !           759: 
        !           760: /* ASCII wrappers for the GSSAPI procedures. */
        !           761: 
        !           762: static int
        !           763: Curl_gss_convert_in_place(OM_uint32 * minor_status, gss_buffer_t buf)
        !           764: 
        !           765: {
        !           766:   unsigned int i = buf->length;
        !           767: 
        !           768:   /* Convert `buf' in place, from EBCDIC to ASCII.
        !           769:      If error, release the buffer and return -1. Else return 0. */
        !           770: 
        !           771:   if(i) {
        !           772:     char *t = malloc(i);
        !           773:     if(!t) {
        !           774:       gss_release_buffer(minor_status, buf);
        !           775: 
        !           776:       if(minor_status)
        !           777:         *minor_status = ENOMEM;
        !           778: 
        !           779:       return -1;
        !           780:     }
        !           781: 
        !           782:     QadrtConvertE2A(t, buf->value, i, i);
        !           783:     memcpy(buf->value, t, i);
        !           784:     free(t);
        !           785:   }
        !           786: 
        !           787:   return 0;
        !           788: }
        !           789: 
        !           790: 
        !           791: OM_uint32
        !           792: Curl_gss_import_name_a(OM_uint32 * minor_status, gss_buffer_t in_name,
        !           793:                        gss_OID in_name_type, gss_name_t * out_name)
        !           794: 
        !           795: {
        !           796:   int rc;
        !           797:   unsigned int i;
        !           798:   gss_buffer_desc in;
        !           799: 
        !           800:   if(!in_name || !in_name->value || !in_name->length)
        !           801:     return gss_import_name(minor_status, in_name, in_name_type, out_name);
        !           802: 
        !           803:   memcpy((char *) &in, (char *) in_name, sizeof(in));
        !           804:   i = in.length;
        !           805: 
        !           806:   in.value = malloc(i + 1);
        !           807:   if(!in.value) {
        !           808:     if(minor_status)
        !           809:       *minor_status = ENOMEM;
        !           810: 
        !           811:     return GSS_S_FAILURE;
        !           812:   }
        !           813: 
        !           814:   QadrtConvertA2E(in.value, in_name->value, i, i);
        !           815:   ((char *) in.value)[i] = '\0';
        !           816:   rc = gss_import_name(minor_status, &in, in_name_type, out_name);
        !           817:   free(in.value);
        !           818:   return rc;
        !           819: }
        !           820: 
        !           821: 
        !           822: OM_uint32
        !           823: Curl_gss_display_status_a(OM_uint32 * minor_status, OM_uint32 status_value,
        !           824:                    int status_type, gss_OID mech_type,
        !           825:                    gss_msg_ctx_t * message_context, gss_buffer_t status_string)
        !           826: 
        !           827: {
        !           828:   int rc;
        !           829: 
        !           830:   rc = gss_display_status(minor_status, status_value, status_type,
        !           831:                               mech_type, message_context, status_string);
        !           832: 
        !           833:   if(rc != GSS_S_COMPLETE || !status_string ||
        !           834:      !status_string->length || !status_string->value)
        !           835:     return rc;
        !           836: 
        !           837:   /* No way to allocate a buffer here, because it will be released by
        !           838:      gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
        !           839:      with ASCII to return it. */
        !           840: 
        !           841:   if(Curl_gss_convert_in_place(minor_status, status_string))
        !           842:     return GSS_S_FAILURE;
        !           843: 
        !           844:   return rc;
        !           845: }
        !           846: 
        !           847: 
        !           848: OM_uint32
        !           849: Curl_gss_init_sec_context_a(OM_uint32 * minor_status,
        !           850:                             gss_cred_id_t cred_handle,
        !           851:                             gss_ctx_id_t * context_handle,
        !           852:                             gss_name_t target_name, gss_OID mech_type,
        !           853:                             gss_flags_t req_flags, OM_uint32 time_req,
        !           854:                             gss_channel_bindings_t input_chan_bindings,
        !           855:                             gss_buffer_t input_token,
        !           856:                             gss_OID * actual_mech_type,
        !           857:                             gss_buffer_t output_token, gss_flags_t * ret_flags,
        !           858:                             OM_uint32 * time_rec)
        !           859: 
        !           860: {
        !           861:   int rc;
        !           862:   gss_buffer_desc in;
        !           863:   gss_buffer_t inp;
        !           864: 
        !           865:   in.value = NULL;
        !           866:   inp = input_token;
        !           867: 
        !           868:   if(inp) {
        !           869:     if(inp->length && inp->value) {
        !           870:       unsigned int i = inp->length;
        !           871: 
        !           872:       in.value = malloc(i + 1);
        !           873:       if(!in.value) {
        !           874:         if(minor_status)
        !           875:           *minor_status = ENOMEM;
        !           876: 
        !           877:         return GSS_S_FAILURE;
        !           878:       }
        !           879: 
        !           880:       QadrtConvertA2E(in.value, input_token->value, i, i);
        !           881:       ((char *) in.value)[i] = '\0';
        !           882:       in.length = i;
        !           883:       inp = &in;
        !           884:     }
        !           885:   }
        !           886: 
        !           887:   rc = gss_init_sec_context(minor_status, cred_handle, context_handle,
        !           888:                              target_name, mech_type, req_flags, time_req,
        !           889:                              input_chan_bindings, inp, actual_mech_type,
        !           890:                              output_token, ret_flags, time_rec);
        !           891:   free(in.value);
        !           892: 
        !           893:   if(rc != GSS_S_COMPLETE || !output_token ||
        !           894:       !output_token->length || !output_token->value)
        !           895:     return rc;
        !           896: 
        !           897:   /* No way to allocate a buffer here, because it will be released by
        !           898:      gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
        !           899:      with ASCII to return it. */
        !           900: 
        !           901:   if(Curl_gss_convert_in_place(minor_status, output_token))
        !           902:     return GSS_S_FAILURE;
        !           903: 
        !           904:   return rc;
        !           905: }
        !           906: 
        !           907: 
        !           908: OM_uint32
        !           909: Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,
        !           910:                               gss_ctx_id_t * context_handle,
        !           911:                               gss_buffer_t output_token)
        !           912: 
        !           913: {
        !           914:   int rc;
        !           915: 
        !           916:   rc = gss_delete_sec_context(minor_status, context_handle, output_token);
        !           917: 
        !           918:   if(rc != GSS_S_COMPLETE || !output_token ||
        !           919:       !output_token->length || !output_token->value)
        !           920:     return rc;
        !           921: 
        !           922:   /* No way to allocate a buffer here, because it will be released by
        !           923:      gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
        !           924:      with ASCII to return it. */
        !           925: 
        !           926:   if(Curl_gss_convert_in_place(minor_status, output_token))
        !           927:     return GSS_S_FAILURE;
        !           928: 
        !           929:   return rc;
        !           930: }
        !           931: 
        !           932: #endif /* HAVE_GSSAPI */
        !           933: 
        !           934: 
        !           935: #ifndef CURL_DISABLE_LDAP
        !           936: 
        !           937: /* ASCII wrappers for the LDAP procedures. */
        !           938: 
        !           939: void *
        !           940: Curl_ldap_init_a(char * host, int port)
        !           941: 
        !           942: {
        !           943:   unsigned int i;
        !           944:   char * ehost;
        !           945:   void * result;
        !           946: 
        !           947:   if(!host)
        !           948:     return (void *) ldap_init(host, port);
        !           949: 
        !           950:   i = strlen(host);
        !           951: 
        !           952:   ehost = malloc(i + 1);
        !           953:   if(!ehost)
        !           954:     return (void *) NULL;
        !           955: 
        !           956:   QadrtConvertA2E(ehost, host, i, i);
        !           957:   ehost[i] = '\0';
        !           958:   result = (void *) ldap_init(ehost, port);
        !           959:   free(ehost);
        !           960:   return result;
        !           961: }
        !           962: 
        !           963: 
        !           964: int
        !           965: Curl_ldap_simple_bind_s_a(void * ld, char * dn, char * passwd)
        !           966: 
        !           967: {
        !           968:   int i;
        !           969:   char * edn;
        !           970:   char * epasswd;
        !           971: 
        !           972:   edn = (char *) NULL;
        !           973:   epasswd = (char *) NULL;
        !           974: 
        !           975:   if(dn) {
        !           976:     i = strlen(dn);
        !           977: 
        !           978:     edn = malloc(i + 1);
        !           979:     if(!edn)
        !           980:       return LDAP_NO_MEMORY;
        !           981: 
        !           982:     QadrtConvertA2E(edn, dn, i, i);
        !           983:     edn[i] = '\0';
        !           984:   }
        !           985: 
        !           986:   if(passwd) {
        !           987:     i = strlen(passwd);
        !           988: 
        !           989:     epasswd = malloc(i + 1);
        !           990:     if(!epasswd) {
        !           991:       free(edn);
        !           992:       return LDAP_NO_MEMORY;
        !           993:     }
        !           994: 
        !           995:     QadrtConvertA2E(epasswd, passwd, i, i);
        !           996:     epasswd[i] = '\0';
        !           997:   }
        !           998: 
        !           999:   i = ldap_simple_bind_s(ld, edn, epasswd);
        !          1000:   free(epasswd);
        !          1001:   free(edn);
        !          1002:   return i;
        !          1003: }
        !          1004: 
        !          1005: 
        !          1006: int
        !          1007: Curl_ldap_search_s_a(void * ld, char * base, int scope, char * filter,
        !          1008:                      char * * attrs, int attrsonly, LDAPMessage * * res)
        !          1009: 
        !          1010: {
        !          1011:   int i;
        !          1012:   int j;
        !          1013:   char * ebase;
        !          1014:   char * efilter;
        !          1015:   char * * eattrs;
        !          1016:   int status;
        !          1017: 
        !          1018:   ebase = (char *) NULL;
        !          1019:   efilter = (char *) NULL;
        !          1020:   eattrs = (char * *) NULL;
        !          1021:   status = LDAP_SUCCESS;
        !          1022: 
        !          1023:   if(base) {
        !          1024:     i = strlen(base);
        !          1025: 
        !          1026:     ebase = malloc(i + 1);
        !          1027:     if(!ebase)
        !          1028:       status = LDAP_NO_MEMORY;
        !          1029:     else {
        !          1030:       QadrtConvertA2E(ebase, base, i, i);
        !          1031:       ebase[i] = '\0';
        !          1032:     }
        !          1033:   }
        !          1034: 
        !          1035:   if(filter && status == LDAP_SUCCESS) {
        !          1036:     i = strlen(filter);
        !          1037: 
        !          1038:     efilter = malloc(i + 1);
        !          1039:     if(!efilter)
        !          1040:       status = LDAP_NO_MEMORY;
        !          1041:     else {
        !          1042:       QadrtConvertA2E(efilter, filter, i, i);
        !          1043:       efilter[i] = '\0';
        !          1044:     }
        !          1045:   }
        !          1046: 
        !          1047:   if(attrs && status == LDAP_SUCCESS) {
        !          1048:     for(i = 0; attrs[i++];)
        !          1049:       ;
        !          1050: 
        !          1051:     eattrs = calloc(i, sizeof(*eattrs));
        !          1052:     if(!eattrs)
        !          1053:       status = LDAP_NO_MEMORY;
        !          1054:     else {
        !          1055:       for(j = 0; attrs[j]; j++) {
        !          1056:         i = strlen(attrs[j]);
        !          1057: 
        !          1058:         eattrs[j] = malloc(i + 1);
        !          1059:         if(!eattrs[j]) {
        !          1060:           status = LDAP_NO_MEMORY;
        !          1061:           break;
        !          1062:         }
        !          1063: 
        !          1064:         QadrtConvertA2E(eattrs[j], attrs[j], i, i);
        !          1065:         eattrs[j][i] = '\0';
        !          1066:         }
        !          1067:       }
        !          1068:     }
        !          1069: 
        !          1070:   if(status == LDAP_SUCCESS)
        !          1071:     status = ldap_search_s(ld, ebase? ebase: "", scope,
        !          1072:                            efilter? efilter: "(objectclass=*)",
        !          1073:                            eattrs, attrsonly, res);
        !          1074: 
        !          1075:   if(eattrs) {
        !          1076:     for(j = 0; eattrs[j]; j++)
        !          1077:       free(eattrs[j]);
        !          1078: 
        !          1079:     free(eattrs);
        !          1080:     }
        !          1081: 
        !          1082:   free(efilter);
        !          1083:   free(ebase);
        !          1084:   return status;
        !          1085: }
        !          1086: 
        !          1087: 
        !          1088: struct berval * *
        !          1089: Curl_ldap_get_values_len_a(void * ld, LDAPMessage * entry, const char * attr)
        !          1090: 
        !          1091: {
        !          1092:   char * cp;
        !          1093:   struct berval * * result;
        !          1094: 
        !          1095:   cp = (char *) NULL;
        !          1096: 
        !          1097:   if(attr) {
        !          1098:     int i = strlen(attr);
        !          1099: 
        !          1100:     cp = malloc(i + 1);
        !          1101:     if(!cp) {
        !          1102:       ldap_set_lderrno(ld, LDAP_NO_MEMORY, NULL,
        !          1103:                        ldap_err2string(LDAP_NO_MEMORY));
        !          1104:       return (struct berval * *) NULL;
        !          1105:     }
        !          1106: 
        !          1107:     QadrtConvertA2E(cp, attr, i, i);
        !          1108:     cp[i] = '\0';
        !          1109:   }
        !          1110: 
        !          1111:   result = ldap_get_values_len(ld, entry, cp);
        !          1112:   free(cp);
        !          1113: 
        !          1114:   /* Result data are binary in nature, so they haven't been
        !          1115:      converted to EBCDIC. Therefore do not convert. */
        !          1116: 
        !          1117:   return result;
        !          1118: }
        !          1119: 
        !          1120: 
        !          1121: char *
        !          1122: Curl_ldap_err2string_a(int error)
        !          1123: 
        !          1124: {
        !          1125:   return set_thread_string(LK_LDAP_ERROR, ldap_err2string(error));
        !          1126: }
        !          1127: 
        !          1128: 
        !          1129: char *
        !          1130: Curl_ldap_get_dn_a(void * ld, LDAPMessage * entry)
        !          1131: 
        !          1132: {
        !          1133:   int i;
        !          1134:   char * cp;
        !          1135:   char * cp2;
        !          1136: 
        !          1137:   cp = ldap_get_dn(ld, entry);
        !          1138: 
        !          1139:   if(!cp)
        !          1140:     return cp;
        !          1141: 
        !          1142:   i = strlen(cp);
        !          1143: 
        !          1144:   cp2 = malloc(i + 1);
        !          1145:   if(!cp2)
        !          1146:     return cp2;
        !          1147: 
        !          1148:   QadrtConvertE2A(cp2, cp, i, i);
        !          1149:   cp2[i] = '\0';
        !          1150: 
        !          1151:   /* No way to allocate a buffer here, because it will be released by
        !          1152:      ldap_memfree() and ldap_memalloc() does not exist. The solution is to
        !          1153:      overwrite the EBCDIC buffer with ASCII to return it. */
        !          1154: 
        !          1155:   strcpy(cp, cp2);
        !          1156:   free(cp2);
        !          1157:   return cp;
        !          1158: }
        !          1159: 
        !          1160: 
        !          1161: char *
        !          1162: Curl_ldap_first_attribute_a(void * ld,
        !          1163:                             LDAPMessage * entry, BerElement * * berptr)
        !          1164: 
        !          1165: {
        !          1166:   int i;
        !          1167:   char * cp;
        !          1168:   char * cp2;
        !          1169: 
        !          1170:   cp = ldap_first_attribute(ld, entry, berptr);
        !          1171: 
        !          1172:   if(!cp)
        !          1173:     return cp;
        !          1174: 
        !          1175:   i = strlen(cp);
        !          1176: 
        !          1177:   cp2 = malloc(i + 1);
        !          1178:   if(!cp2)
        !          1179:     return cp2;
        !          1180: 
        !          1181:   QadrtConvertE2A(cp2, cp, i, i);
        !          1182:   cp2[i] = '\0';
        !          1183: 
        !          1184:   /* No way to allocate a buffer here, because it will be released by
        !          1185:      ldap_memfree() and ldap_memalloc() does not exist. The solution is to
        !          1186:      overwrite the EBCDIC buffer with ASCII to return it. */
        !          1187: 
        !          1188:   strcpy(cp, cp2);
        !          1189:   free(cp2);
        !          1190:   return cp;
        !          1191: }
        !          1192: 
        !          1193: 
        !          1194: char *
        !          1195: Curl_ldap_next_attribute_a(void * ld,
        !          1196:                            LDAPMessage * entry, BerElement * berptr)
        !          1197: 
        !          1198: {
        !          1199:   int i;
        !          1200:   char * cp;
        !          1201:   char * cp2;
        !          1202: 
        !          1203:   cp = ldap_next_attribute(ld, entry, berptr);
        !          1204: 
        !          1205:   if(!cp)
        !          1206:     return cp;
        !          1207: 
        !          1208:   i = strlen(cp);
        !          1209: 
        !          1210:   cp2 = malloc(i + 1);
        !          1211:   if(!cp2)
        !          1212:     return cp2;
        !          1213: 
        !          1214:   QadrtConvertE2A(cp2, cp, i, i);
        !          1215:   cp2[i] = '\0';
        !          1216: 
        !          1217:   /* No way to allocate a buffer here, because it will be released by
        !          1218:      ldap_memfree() and ldap_memalloc() does not exist. The solution is to
        !          1219:      overwrite the EBCDIC buffer with ASCII to return it. */
        !          1220: 
        !          1221:   strcpy(cp, cp2);
        !          1222:   free(cp2);
        !          1223:   return cp;
        !          1224: }
        !          1225: 
        !          1226: #endif /* CURL_DISABLE_LDAP */
        !          1227: 
        !          1228: 
        !          1229: static int
        !          1230: sockaddr2ebcdic(struct sockaddr_storage *dstaddr,
        !          1231:                 const struct sockaddr *srcaddr, int srclen)
        !          1232: {
        !          1233:   const struct sockaddr_un *srcu;
        !          1234:   struct sockaddr_un *dstu;
        !          1235:   unsigned int i;
        !          1236:   unsigned int dstsize;
        !          1237: 
        !          1238:   /* Convert a socket address to job CCSID, if needed. */
        !          1239: 
        !          1240:   if(!srcaddr || srclen < offsetof(struct sockaddr, sa_family) +
        !          1241:      sizeof(srcaddr->sa_family) || srclen > sizeof(*dstaddr)) {
        !          1242:     errno = EINVAL;
        !          1243:     return -1;
        !          1244:     }
        !          1245: 
        !          1246:   memcpy((char *) dstaddr, (char *) srcaddr, srclen);
        !          1247: 
        !          1248:   switch (srcaddr->sa_family) {
        !          1249: 
        !          1250:   case AF_UNIX:
        !          1251:     srcu = (const struct sockaddr_un *) srcaddr;
        !          1252:     dstu = (struct sockaddr_un *) dstaddr;
        !          1253:     dstsize = sizeof(*dstaddr) - offsetof(struct sockaddr_un, sun_path);
        !          1254:     srclen -= offsetof(struct sockaddr_un, sun_path);
        !          1255:     i = QadrtConvertA2E(dstu->sun_path, srcu->sun_path, dstsize - 1, srclen);
        !          1256:     dstu->sun_path[i] = '\0';
        !          1257:     srclen = i + offsetof(struct sockaddr_un, sun_path);
        !          1258:     }
        !          1259: 
        !          1260:   return srclen;
        !          1261: }
        !          1262: 
        !          1263: 
        !          1264: static int
        !          1265: sockaddr2ascii(struct sockaddr *dstaddr, int dstlen,
        !          1266:                const struct sockaddr_storage *srcaddr, int srclen)
        !          1267: {
        !          1268:   const struct sockaddr_un *srcu;
        !          1269:   struct sockaddr_un *dstu;
        !          1270:   unsigned int dstsize;
        !          1271: 
        !          1272:   /* Convert a socket address to ASCII, if needed. */
        !          1273: 
        !          1274:   if(!srclen)
        !          1275:     return 0;
        !          1276:   if(srclen > dstlen)
        !          1277:     srclen = dstlen;
        !          1278:   if(!srcaddr || srclen < 0) {
        !          1279:     errno = EINVAL;
        !          1280:     return -1;
        !          1281:     }
        !          1282: 
        !          1283:   memcpy((char *) dstaddr, (char *) srcaddr, srclen);
        !          1284: 
        !          1285:   if(srclen >= offsetof(struct sockaddr_storage, ss_family) +
        !          1286:      sizeof(srcaddr->ss_family)) {
        !          1287:     switch (srcaddr->ss_family) {
        !          1288: 
        !          1289:     case AF_UNIX:
        !          1290:       srcu = (const struct sockaddr_un *) srcaddr;
        !          1291:       dstu = (struct sockaddr_un *) dstaddr;
        !          1292:       dstsize = dstlen - offsetof(struct sockaddr_un, sun_path);
        !          1293:       srclen -= offsetof(struct sockaddr_un, sun_path);
        !          1294:       if(dstsize > 0 && srclen > 0) {
        !          1295:         srclen = QadrtConvertE2A(dstu->sun_path, srcu->sun_path,
        !          1296:                                  dstsize - 1, srclen);
        !          1297:         dstu->sun_path[srclen] = '\0';
        !          1298:       }
        !          1299:       srclen += offsetof(struct sockaddr_un, sun_path);
        !          1300:     }
        !          1301:   }
        !          1302: 
        !          1303:   return srclen;
        !          1304: }
        !          1305: 
        !          1306: 
        !          1307: int
        !          1308: Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen)
        !          1309: {
        !          1310:   int i;
        !          1311:   struct sockaddr_storage laddr;
        !          1312: 
        !          1313:   i = sockaddr2ebcdic(&laddr, destaddr, addrlen);
        !          1314: 
        !          1315:   if(i < 0)
        !          1316:     return -1;
        !          1317: 
        !          1318:   return connect(sd, (struct sockaddr *) &laddr, i);
        !          1319: }
        !          1320: 
        !          1321: 
        !          1322: int
        !          1323: Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen)
        !          1324: {
        !          1325:   int i;
        !          1326:   struct sockaddr_storage laddr;
        !          1327: 
        !          1328:   i = sockaddr2ebcdic(&laddr, localaddr, addrlen);
        !          1329: 
        !          1330:   if(i < 0)
        !          1331:     return -1;
        !          1332: 
        !          1333:   return bind(sd, (struct sockaddr *) &laddr, i);
        !          1334: }
        !          1335: 
        !          1336: 
        !          1337: int
        !          1338: Curl_os400_sendto(int sd, char * buffer, int buflen, int flags,
        !          1339:                                 struct sockaddr * dstaddr, int addrlen)
        !          1340: {
        !          1341:   int i;
        !          1342:   struct sockaddr_storage laddr;
        !          1343: 
        !          1344:   i = sockaddr2ebcdic(&laddr, dstaddr, addrlen);
        !          1345: 
        !          1346:   if(i < 0)
        !          1347:     return -1;
        !          1348: 
        !          1349:   return sendto(sd, buffer, buflen, flags, (struct sockaddr *) &laddr, i);
        !          1350: }
        !          1351: 
        !          1352: 
        !          1353: int
        !          1354: Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
        !          1355:                                 struct sockaddr * fromaddr, int * addrlen)
        !          1356: {
        !          1357:   int rcvlen;
        !          1358:   struct sockaddr_storage laddr;
        !          1359:   int laddrlen = sizeof(laddr);
        !          1360: 
        !          1361:   if(!fromaddr || !addrlen || *addrlen <= 0)
        !          1362:     return recvfrom(sd, buffer, buflen, flags, fromaddr, addrlen);
        !          1363: 
        !          1364:   laddr.ss_family = AF_UNSPEC;          /* To detect if unused. */
        !          1365:   rcvlen = recvfrom(sd, buffer, buflen, flags,
        !          1366:                     (struct sockaddr *) &laddr, &laddrlen);
        !          1367: 
        !          1368:   if(rcvlen < 0)
        !          1369:     return rcvlen;
        !          1370: 
        !          1371:   if(laddr.ss_family == AF_UNSPEC)
        !          1372:     laddrlen = 0;
        !          1373:   else {
        !          1374:     laddrlen = sockaddr2ascii(fromaddr, *addrlen, &laddr, laddrlen);
        !          1375:     if(laddrlen < 0)
        !          1376:       return laddrlen;
        !          1377:   }
        !          1378:   *addrlen = laddrlen;
        !          1379:   return rcvlen;
        !          1380: }
        !          1381: 
        !          1382: 
        !          1383: int
        !          1384: Curl_os400_getpeername(int sd, struct sockaddr *addr, int *addrlen)
        !          1385: {
        !          1386:   struct sockaddr_storage laddr;
        !          1387:   int laddrlen = sizeof(laddr);
        !          1388:   int retcode = getpeername(sd, (struct sockaddr *) &laddr, &laddrlen);
        !          1389: 
        !          1390:   if(!retcode) {
        !          1391:     laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen);
        !          1392:     if(laddrlen < 0)
        !          1393:       return laddrlen;
        !          1394:     *addrlen = laddrlen;
        !          1395:   }
        !          1396: 
        !          1397:   return retcode;
        !          1398: }
        !          1399: 
        !          1400: 
        !          1401: int
        !          1402: Curl_os400_getsockname(int sd, struct sockaddr *addr, int *addrlen)
        !          1403: {
        !          1404:   struct sockaddr_storage laddr;
        !          1405:   int laddrlen = sizeof(laddr);
        !          1406:   int retcode = getsockname(sd, (struct sockaddr *) &laddr, &laddrlen);
        !          1407: 
        !          1408:   if(!retcode) {
        !          1409:     laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen);
        !          1410:     if(laddrlen < 0)
        !          1411:       return laddrlen;
        !          1412:     *addrlen = laddrlen;
        !          1413:   }
        !          1414: 
        !          1415:   return retcode;
        !          1416: }
        !          1417: 
        !          1418: 
        !          1419: #ifdef HAVE_LIBZ
        !          1420: const char *
        !          1421: Curl_os400_zlibVersion(void)
        !          1422: 
        !          1423: {
        !          1424:   return set_thread_string(LK_ZLIB_VERSION, zlibVersion());
        !          1425: }
        !          1426: 
        !          1427: 
        !          1428: int
        !          1429: Curl_os400_inflateInit_(z_streamp strm, const char * version, int stream_size)
        !          1430: 
        !          1431: {
        !          1432:   z_const char * msgb4 = strm->msg;
        !          1433:   int ret;
        !          1434: 
        !          1435:   ret = inflateInit(strm);
        !          1436: 
        !          1437:   if(strm->msg != msgb4)
        !          1438:     strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
        !          1439: 
        !          1440:   return ret;
        !          1441: }
        !          1442: 
        !          1443: 
        !          1444: int
        !          1445: Curl_os400_inflateInit2_(z_streamp strm, int windowBits,
        !          1446:                                         const char * version, int stream_size)
        !          1447: 
        !          1448: {
        !          1449:   z_const char * msgb4 = strm->msg;
        !          1450:   int ret;
        !          1451: 
        !          1452:   ret = inflateInit2(strm, windowBits);
        !          1453: 
        !          1454:   if(strm->msg != msgb4)
        !          1455:     strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
        !          1456: 
        !          1457:   return ret;
        !          1458: }
        !          1459: 
        !          1460: 
        !          1461: int
        !          1462: Curl_os400_inflate(z_streamp strm, int flush)
        !          1463: 
        !          1464: {
        !          1465:   z_const char * msgb4 = strm->msg;
        !          1466:   int ret;
        !          1467: 
        !          1468:   ret = inflate(strm, flush);
        !          1469: 
        !          1470:   if(strm->msg != msgb4)
        !          1471:     strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
        !          1472: 
        !          1473:   return ret;
        !          1474: }
        !          1475: 
        !          1476: 
        !          1477: int
        !          1478: Curl_os400_inflateEnd(z_streamp strm)
        !          1479: 
        !          1480: {
        !          1481:   z_const char * msgb4 = strm->msg;
        !          1482:   int ret;
        !          1483: 
        !          1484:   ret = inflateEnd(strm);
        !          1485: 
        !          1486:   if(strm->msg != msgb4)
        !          1487:     strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
        !          1488: 
        !          1489:   return ret;
        !          1490: }
        !          1491: 
        !          1492: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>