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