2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
5 * Copyright (C) 2005 - 2007 The AROS Dev Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 #include <aros/libcall.h>
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <sys/syslog.h>
30 #include <sys/errno.h>
32 #include <kern/amiga_includes.h>
34 #include <api/amiga_api.h>
35 #include <api/amiga_libcallentry.h>
36 #include <api/allocdatabuffer.h>
38 #include <api/apicalls.h>
39 #include <api/amiga_kernvars.h>
42 #include <bsdsocket/socketbasetags.h>
45 * va_set() macro is used to convert from AmigaOS-style arguments array
46 * to standard SVR4 va_list structure. We just fabricate such a structure
47 * where reg_save_area is already ended up and next argument will be
48 * picked up from overflow_arg_area which is our array. Note that we
49 * don't need va_start() and va_end() in this case
52 #define va_set(ap, args) \
55 ap->overflow_arg_area = args;
59 #define va_set(ap, args) \
61 ap->fp_offset = 304; \
62 ap->overflow_arg_area = args;
66 #define va_set(ap, args) \
71 #define va_set(ap, args) \
75 extern const char * const __sys_errlist
[];
76 extern const int __sys_nerr
;
77 extern const char * const h_errlist
[];
78 extern const int h_nerr
;
79 extern const char * const io_errlist
[];
80 extern const short io_nerr
;
81 extern const char * const sana2io_errlist
[];
82 extern const short sana2io_nerr
;
83 extern const char * const sana2wire_errlist
[];
84 extern const short sana2wire_nerr
;
85 extern STRPTR version
;
86 extern struct kernel_var kvars
[];
89 REG(a6, struct SocketBase *libPtr))*/
91 struct SocketBase
*, libPtr
, 27, UL
)
94 return (LONG
)readErrnoValue(libPtr
);
98 LONG
__SetErrnoPtr(VOID
*err_p
, UBYTE size
, struct SocketBase
*libPtr
)
100 if (size
== 4 || size
== 2 || size
== 1) {
101 if (size
& 0x1 || !((IPTR
)err_p
& 0x1)) { /* either odd size or address even */
102 libPtr
->errnoSize
= size
;
103 libPtr
->errnoPtr
= err_p
;
108 writeErrnoValue(libPtr
, EINVAL
);
112 AROS_LH2(LONG
, SetErrnoPtr
,
113 AROS_LHA(VOID
*, err_p
, A0
),
114 AROS_LHA(UBYTE
, size
, D0
),
115 struct SocketBase
*, libPtr
, 28, UL
)
118 return __SetErrnoPtr(err_p
, size
, libPtr
);
122 /*VOID SAVEDS Syslog(
124 REG(a0, const char *fmt),
126 REG(a6, struct SocketBase *libPtr))*/
127 AROS_LH3(VOID
, Syslog
,
128 AROS_LHA(ULONG
, pri
, D0
),
129 AROS_LHA(const char *, fmt
, A0
),
130 AROS_LHA(IPTR
*, ap
, A1
),
131 struct SocketBase
*, libPtr
, 43, UL
)
138 register char *p
= fmt_cpy
;
146 /* check for invalid bits or no priority set */
148 DSYSLOG(KPrintF("Priority is zero\n");)
151 if (pri
&~ (LOG_PRIMASK
|LOG_FACMASK
)) {
152 DSYSLOG(KPrintF("Bad bits in priority/facility value 0x%08lx\n", pri
);)
155 if (!(LOG_MASK(LOG_PRI(pri
)) & libPtr
->LogMask
)) {
156 DSYSLOG(KPrintF("Priority value %lu is masked out\n", LOG_PRI(pri
));)
160 saved_errno
= readErrnoValue(libPtr
);
161 if (saved_errno
>= __sys_nerr
)
162 saved_errno
= 0; /* XXX */
164 /* set default facility if none specified */
165 if ((pri
& LOG_FACMASK
) == 0)
166 pri
|= libPtr
->LogFacility
;
168 if (libPtr
->LogTag
) {
169 DSYSLOG(KPrintF("LogTag: %s", libPtr
->LogTag
);)
172 t1
+= sprintf(t1
, "%s", libPtr
->LogTag
);
174 DSYSLOG(else KPrintF("LogTag: <NULL>");)
175 DSYSLOG(KPrintF(", message: %s\n", fmt
);)
176 if (libPtr
->LogStat
& LOG_PID
) {
181 sprintf(t1
, "[%p]", libPtr
->thisTask
);
185 * Build the new format string
187 /*if (libPtr->LogTag) {
188 p += sprintf(p, libPtr->LogTag);
190 if (libPtr->LogStat & LOG_PID) {
191 p += sprintf(p, "[%lx]", libPtr->thisTask);
193 if (libPtr->LogTag) {
198 * Substitute error message for %m.
204 for (t1
= p
; ch
= *fmt
; ++fmt
) {
210 else if (fmt
[1] == 'm') {
212 for (t2
= __sys_errlist
[saved_errno
]; *t1
= *t2
++; ++t1
)
221 vlog(pri
, t
, fmt_cpy
, _ap
);
225 /*VOID SAVEDS SetSocketSignals(
226 REG(d0, ULONG sigintrmask),
227 REG(d1, ULONG sigiomask),
228 REG(d2, ULONG sigurgmask),
229 REG(a6, struct SocketBase *libPtr))*/
230 AROS_LH3(VOID
, SetSocketSignals
,
231 AROS_LHA(ULONG
, sigintrmask
, D0
),
232 AROS_LHA(ULONG
, sigiomask
, D1
),
233 AROS_LHA(ULONG
, sigurgmask
, D2
),
234 struct SocketBase
*, libPtr
, 22, UL
)
238 DSYSCALLS(log(LOG_DEBUG
,"SetSocketSignals(0x%08lx, 0x%08lx, 0x%08lx) called", sigintrmask
, sigiomask
, sigurgmask
);)
240 * The operations below are atomic so no need to protect them
242 libPtr
->sigIntrMask
= sigintrmask
;
243 libPtr
->sigIOMask
= sigiomask
;
244 libPtr
->sigUrgMask
= sigurgmask
;
248 /*LONG getdtablesize(
249 REG(a6, struct SocketBase *libPtr))*/
250 AROS_LH0(LONG
, getdtablesize
,
251 struct SocketBase
*, libPtr
, 23, UL
)
254 DSYSCALLS(log(LOG_DEBUG
,"getdtablesize(): returned %ld", libPtr
->dTableSize
);)
255 return (LONG
)libPtr
->dTableSize
;
259 static int getLastSockFd(struct SocketBase
*libPtr
)
261 int bit
, lastmlong
= (libPtr
->dTableSize
- 1) / NFDBITS
;
262 ULONG
*smaskp
, cmask
, rmask
;
264 for (smaskp
= (ULONG
*)(libPtr
->dTable
+ libPtr
->dTableSize
+ lastmlong
);
265 lastmlong
>= 0; smaskp
--, lastmlong
--)
273 if ((rmask
= cmask
& 0xFFFF0000)) { bit
= 16; cmask
= rmask
; }
275 if ((rmask
= cmask
& 0xFF00FF00)) { bit
+= 8; cmask
= rmask
; }
276 if ((rmask
= cmask
& 0xF0F0F0F0)) { bit
+= 4; cmask
= rmask
; }
277 if ((rmask
= cmask
& 0xCCCCCCCC)) { bit
+= 2; cmask
= rmask
; }
278 if ((rmask
= cmask
& 0xAAAAAAAA)) bit
+= 1;
280 return lastmlong
* 32 + bit
;
284 * Set size of descriptor tab|e
287 setdtablesize(struct SocketBase
* libPtr
, UWORD size
)
290 LONG oldsize
= (LONG
)libPtr
->dTableSize
;
292 struct socket
** dTable
;
293 int olddmasksize
, copydmasksize
, dmasksize
;
295 if (size
< oldsize
) {
298 if ((i
= getLastSockFd(libPtr
)) > size
)
305 olddmasksize
= (oldsize
- 1) / NFDBITS
+ 1;
306 copydmasksize
= (copysize
- 1) / NFDBITS
+ 1;
307 dmasksize
= (size
- 1) / NFDBITS
+ 1;
309 if ((dTable
= AllocMem(size
* sizeof (struct socket
*) +
310 dmasksize
* sizeof (fd_mask
),
311 MEMF_PUBLIC
|MEMF_CLEAR
)) == NULL
)
314 aligned_bcopy(libPtr
->dTable
, dTable
, copysize
* sizeof (struct socket
*));
315 aligned_bcopy(libPtr
->dTable
+ oldsize
, dTable
+ size
,
316 copydmasksize
* sizeof (fd_mask
));
318 FreeMem(libPtr
->dTable
, oldsize
* sizeof (struct socket
*) +
319 olddmasksize
* sizeof (fd_mask
));
321 libPtr
->dTable
= dTable
;
322 libPtr
->dTableSize
= size
;
328 /* GNU C 4.x and higher really don't like to
329 * have the l-value type-punned
331 #define IPTR_ASSIGN(s,v) s = (__typeof__(s))(v)
332 #define LONG_ASSIGN(s,v) IPTR_ASSIGN(s, v)
334 #define IPTR_ASSIGN(s, v) *(IPTR *)(s) = v
335 #define LONG_ASSIGN(s, v) *(LONG *)(s) = v
338 #define CASE_IPTR(code, baseField)\
339 case (code << SBTB_CODE): /* get */ \
340 *tagData = (IPTR)libPtr->baseField;\
342 case (code << SBTB_CODE) | SBTF_SET: /* set */\
343 IPTR_ASSIGN(libPtr->baseField, *(tagData));\
346 #define CASE_LONG(code, baseField)\
347 case (code << SBTB_CODE): /* get */ \
348 *tagData = (LONG)libPtr->baseField;\
350 case (code << SBTB_CODE) | SBTF_SET: /* set */\
351 LONG_ASSIGN(libPtr->baseField, *(tagData));\
354 #define CASE_WORD(code, baseField)\
355 case (code << SBTB_CODE): /* get */ \
356 *tagData = (ULONG)libPtr->baseField;\
358 case (code << SBTB_CODE) | SBTF_SET: /* set */\
359 *(UWORD *)&libPtr->baseField = (UWORD)*tagData;\
362 #define CASE_BYTE(code, baseField)\
363 case (code << SBTB_CODE): /* get */ \
364 *tagData = (ULONG)libPtr->baseField;\
366 case (code << SBTB_CODE) | SBTF_SET: /* set */\
367 *(UBYTE *)&libPtr->baseField = (UBYTE)*tagData;\
370 #define CASE_FLAG(code, flag)\
371 case (code << SBTB_CODE): /* get */ \
372 *tagData = ((ULONG)libPtr->flags & (flag)) != 0;\
374 case (code << SBTB_CODE) | SBTF_SET: /* set */\
376 *(UBYTE *)&libPtr->flags |= (flag);\
378 *(UBYTE *)&libPtr->flags &= ~(flag);\
381 /****** bsdsocket.library/SocketBaseTagList ***********************************
384 SocketBaseTagList - Set/Get SocketBase attributes.
387 #include <amitcp/socketbasetags.h>
389 ULONG SocketBaseTagList(struct TagItem *);
391 error = SocketBaseTagList(taglist)
394 error = SocketBaseTags(ULONG tag, ...);
397 Set or get a list of (mostly) SocketBase instance dependent attributes
401 These functions expect as their argument a standard tag list, one or
402 several array of struct TagItem as defined in the header file
403 <utility/tagitem.h>. The structure contains two fields: ti_Tag and
404 ti_Data. The ti_Tag field contains tag code, which determines what
405 the SocketBaseTagList() should do with its argument, the ti_Data
408 The include file <amitcp/socketbasetags.h> defines macros for base tag
409 code values. Base tag code macros begin with `SBTC_' (as Socket Base
410 Tag Code). The base tag value defines what data item the tag item
413 The tag code contains other information besides the referred data
414 item. It controls, whether the SocketBaseTagList() should set or get
415 the appropriate parameter, and whether the argument of the tag in
416 question is passed by value or by reference.
418 The include file <amitcp/socketbasetags.h> defines the following
419 macros, which are used to construct the ti_Tag values from the base
422 SBTM_GETREF(code) - get by reference
423 SBTM_GETVAL(code) - get by value
424 SBTM_SETREF(code) - set by reference
425 SBTM_SETVAL(code) - set by value
427 If the actual data is stored directly into the ti_Data field, you
428 should use the 'by value' macros, SBTM_GETVAL() or SBTM_SETVAL().
429 However, if the ti_Data field contains a pointer to actual data, you
430 should use the 'by reference' macros, SBTM_GETREF() or SBTM_SETREF().
431 In either case the actual data should always be a LONG aligned to even
434 According the used tag naming scheme a tag which has "PTR" suffix
435 takes an pointer as its argument. Don't mix the pointer arguments
436 with 'by reference' argument passing. It is possible to pass a
437 pointer by reference (in which case the ti_Data is a pointer to the
440 The list of all defined base tag codes is as follows:
442 SBTC_BREAKMASK Tag data contains the INTR signal mask. If
443 the calling task receives a signal in the
444 INTR mask, the AmiTCP interrupts current
445 function calls and returns with the error
446 code EINTR. The INTR mask defaults to the
447 CTRL-C signal (SIGBREAKF_C, bit 12).
449 SBTC_DTABLESIZE Socket Descriptor Table size. This
452 SBTC_ERRNO The errno value. The values are defined in
458 SBTC_ERRNOPTR(size) Set (only) the pointer to the errno
459 variable defined by the program. AmiTCP
460 defines a value for this by default, but
461 the application must set the pointer (and
462 the size of the errno) with one of these
463 tags, if it wishes to access the errno
466 The SBTC_ERRNOPTR(size) is a macro, which
467 expands to one of the other (BYTE, WORD or
468 LONG) tag codes, meaning that only 1, 2
469 and 4 are legal size values.
471 The netlib autoinit.c sets the errno
472 pointer for the application, if the
473 application is linked with it.
475 SBTC_ERRNOSTRPTR Returns an error string pointer describing
476 the errno value given on input. You can not
477 set the error message, only get is allowed.
479 On call the ti_Data must contain the error
480 code number. On return the ti_Data is
481 assigned to the string pointer. (*ti_Data,
482 if passed by reference). See the file
483 <sys/errno.h> for symbolic definitions for
486 SBTC_FDCALLBACK A callback function pointer for coordination
487 of file descriptor usage between AmiTCP and
488 link-library. By default no callback is
489 called and the value of this pointer is
490 NULL. The prototype for the callback
493 int error = fdCallback(int fd, int action);
498 error - 0 for success or one of the error
499 codes in <sys/errno.h> in case of
500 error. The AmiTCP API function
501 that calls the callback usually
502 returns the 'error' back to the
503 caller without any further
506 fd - file descriptor number to take
509 action - one of the following actions
511 <amitcp/socketbasetags.h>):
513 FDCB_FREE - mark the 'fd' as
515 library structure. If
522 FDCB_ALLOC - mark the 'fd'
526 FDCB_CHECK - check if the 'fd' is
528 returned, the 'fd' is
529 marked as used in the
530 AmiTCP/IP structures.
532 The AmiTCP/IP calls the callback every time
533 a socket descriptor is allocated or freed.
534 AmiTCP/IP uses the FDCB_CHECK before actual
535 allocation to check that it agrees with the
536 link library on the next free descriptor
537 number. Thus the link library doesn't need
538 to tell the AmiTCP if it creates a new file
539 handle in open(), for example.
541 See file _chkufb.c on the net.lib sources
542 for an example implementation of the
543 callback function for the SAS/C.
545 SBTC_HERRNO The name resolver error code value. Get
546 this to find out why the gethostbyname()
547 or gethostbyaddr() failed. The values are
550 SBTC_HERRNOSTRPTR Returns host error string for error number
551 in tag data. Host error is set on
552 unsuccesful gethostbyname() and
553 gethostbyaddr() calls. See the file
554 <netdb.h> for the symbolic definitions for
557 Notes for the SBTC_ERRNOSTRPTR apply also
560 SBTC_IOERRNOSTRPTR Returns an error string for standard
561 AmigaOS I/O error number as defined in the
562 header file <exec/errors.h>. Note that the
563 error number taken by this tag code is
564 positive, so the error codes must be
565 negated (to be positive). The positive
566 error codes depend on the particular IO
567 device, the standard Sana-II error codes
568 can be retrieved by the tag code
571 Notes for the SBTC_ERRNOSTRPTR apply also
574 SBTC_LOGFACILITY Facility code for the syslog messages as
575 defined in the header file <sys/syslog.h>.
576 Defaults to LOG_USER.
578 SBTC_LOGMASK Sets the filter mask of the syslog
579 messages. By default the mask is 0xff,
580 meaning that all messages are passed to the
583 SBTC_LOGSTAT Syslog options defined in <sys/syslog.h>.
585 SBTC_LOGTAGPTR A pointer to a string which is used by
586 syslog() to mark individual syslog
587 messages. This defaults to NULL, but is
588 set to the name of the calling program by
589 the autoinit code in netlib:autoinit.c.
590 This is for compatibility with pre-3.0
593 SBTC_S2ERRNOSTRPTR Returns an error string for a Sana-II
594 specific I/O error code as defined in the
595 header file <devices/sana2.h>.
597 Notes for the SBTC_ERRNOSTRPTR apply also
600 SBTC_S2WERRNOSTRPTR Returns an error string for a Sana-II Wire
601 Error code as defined in the header file
604 Notes for the SBTC_ERRNOSTRPTR apply also
607 SBTC_SIGIOMASK The calling task is sent the signals
608 specified by mask in tag data when
609 asynhronous I/O is to be notified. The
610 default value is zero, ie. no signal is
613 SBTC_SIGURGMASK The calling task is sent the signals
614 specified by mask in tag data when urgent
615 data for the TCP arrives. The default value
616 is zero, ie. no signal is sent.
619 Returns 0 on success, and a (positive) index of the failing tag on
620 error. Note that the value 1 means _first_ TagItem, 2 the second one,
621 and so on. The return value is NOT a C-language index, which are 0
625 To be written, see net.lib sources for various examples.
633 <netinclude:amitcp/socketbasetags.h>, <include:utility/tagitem.h>
635 *****************************************************************************
640 SBTC_COMPAT43 Tag data is handled as boolean. If it is
641 true, AmiTCP/IP uses 4.3BSD compatible
642 sockaddr structure for this application.
644 The unreleased AS225r2 uses also 4.3BSD-
645 compatible sockaddr structures.
650 /*ULONG SAVEDS SocketBaseTagList(
651 REG(a0, struct TagItem *tags),
652 REG(a6, struct SocketBase *libPtr))*/
653 AROS_LH1(ULONG
, SocketBaseTagList
,
654 AROS_LHA(struct TagItem
*, tags
, A0
),
655 struct SocketBase
*, libPtr
, 49, UL
)
664 static const char * const strErr
= "Errlist lookup error";
668 while((tag
= tags
->ti_Tag
) != TAG_END
) {
669 if (tag
& TAG_USER
) { /* TAG_USER is the sign bit */
670 /* get pointer to the actual data */
671 tagData
= ((UWORD
)tag
& SBTF_REF
) ?
672 (IPTR
*)tags
->ti_Data
: &tags
->ti_Data
;
675 if (((UWORD
)tag
& ~(SBTF_REF
)) == ((SBTC_SIGEVENTMASK
<< SBTB_CODE
) | SBTF_SET
))
676 log(LOG_DEBUG
,"SBTC_SIGEVENTMASK set to 0x%08lx", *tagData
);
679 switch ((UWORD
)tag
& ~SBTF_REF
) {
681 CASE_LONG( SBTC_BREAKMASK
, sigIntrMask
);
683 CASE_LONG( SBTC_SIGIOMASK
, sigIOMask
);
685 CASE_LONG( SBTC_SIGURGMASK
, sigUrgMask
);
687 CASE_LONG( SBTC_SIGEVENTMASK
, sigEventMask
);
689 case (SBTC_ERRNO
<< SBTB_CODE
): /* get */
690 *tagData
= (IPTR
)readErrnoValue(libPtr
);
692 case (SBTC_ERRNO
<< SBTB_CODE
) | SBTF_SET
: /* set */
693 writeErrnoValue(libPtr
, *tagData
);
696 case (SBTC_HERRNO
<< SBTB_CODE
): /* get */
697 *tagData
= (IPTR
)*libPtr
->hErrnoPtr
;
699 case (SBTC_HERRNO
<< SBTB_CODE
) | SBTF_SET
: /* set */
700 *libPtr
->hErrnoPtr
= (IPTR
) *tagData
;
703 case (SBTC_DTABLESIZE
<< SBTB_CODE
): /* get */
704 *tagData
= (IPTR
)libPtr
->dTableSize
;
706 case (SBTC_DTABLESIZE
<< SBTB_CODE
) | SBTF_SET
: /* set */
707 if ((tmp
= (WORD
)*tagData
) > 0)
708 setdtablesize(libPtr
, tmp
);
711 CASE_IPTR( SBTC_FDCALLBACK
, fdCallback
);
713 CASE_BYTE( SBTC_LOGSTAT
, LogStat
);
715 CASE_IPTR( SBTC_LOGTAGPTR
, LogTag
);
717 case (SBTC_LOGFACILITY
<< SBTB_CODE
): /* get */
718 *tagData
= (ULONG
)libPtr
->LogFacility
;
720 case (SBTC_LOGFACILITY
<< SBTB_CODE
) | SBTF_SET
: /* set */
721 if ((utmp
= (UWORD
)*tagData
) != 0 && (utmp
&~ LOG_FACMASK
) == 0)
722 libPtr
->LogFacility
= utmp
;
725 case (SBTC_LOGMASK
<< SBTB_CODE
): /* get */
726 *tagData
= (ULONG
)libPtr
->LogMask
;
728 case (SBTC_LOGMASK
<< SBTB_CODE
) | SBTF_SET
: /* set */
729 if ((utmp
= (UWORD
)*tagData
) != 0)
730 libPtr
->LogMask
= (UBYTE
)utmp
;
733 case SBTC_ERRNOSTRPTR
<< SBTB_CODE
:
735 utmp
= (UWORD
)*tagData
;
736 /* return string pointer */
737 *tagData
= (IPTR
)((utmp
>= __sys_nerr
) ?
738 strErr
: __sys_errlist
[utmp
]);
740 case SBTC_HERRNOSTRPTR
<< SBTB_CODE
:
742 utmp
= (UWORD
)*tagData
;
743 /* return string pointer */
744 *tagData
= (IPTR
)((utmp
>= h_nerr
) ?
745 strErr
: h_errlist
[utmp
]);
747 case SBTC_IOERRNOSTRPTR
<< SBTB_CODE
:
749 utmp
= (UWORD
)*tagData
;
750 /* return string pointer */
751 *tagData
= (IPTR
)((utmp
>= io_nerr
) ?
752 strErr
: io_errlist
[utmp
]);
754 case SBTC_S2ERRNOSTRPTR
<< SBTB_CODE
:
756 utmp
= (UWORD
)*tagData
;
757 /* return string pointer */
758 *tagData
= (IPTR
)((utmp
>= sana2io_nerr
) ?
759 strErr
: sana2io_errlist
[utmp
]);
761 case SBTC_S2WERRNOSTRPTR
<< SBTB_CODE
:
763 utmp
= (UWORD
)*tagData
;
764 /* return string pointer */
765 *tagData
= (IPTR
)((utmp
>= sana2wire_nerr
) ?
766 strErr
: sana2wire_errlist
[utmp
]);
769 case (SBTC_ERRNOBYTEPTR
<< SBTB_CODE
) | SBTF_SET
: /* set */
770 if (__SetErrnoPtr((VOID
*)*tagData
, 1, libPtr
) < 0)
773 case (SBTC_ERRNOWORDPTR
<< SBTB_CODE
) | SBTF_SET
: /* set */
774 if (__SetErrnoPtr((VOID
*)*tagData
, 2, libPtr
) < 0)
777 case (SBTC_ERRNOLONGPTR
<< SBTB_CODE
) | SBTF_SET
: /* set */
778 if (__SetErrnoPtr((VOID
*)*tagData
, 4, libPtr
) < 0)
782 CASE_IPTR( SBTC_HERRNOLONGPTR
, hErrnoPtr
);
784 case (SBTC_RELEASESTRPTR
<< SBTB_CODE
): /* get */
785 *tagData
= (IPTR
)&version
[6];
789 CASE_FLAG( SBTC_COMPAT43
, SBFB_COMPAT43
);
796 else { /* TAG_USER not set */
797 switch(tags
->ti_Tag
) {
801 tags
= (struct TagItem
*)tags
->ti_Data
;
808 return errIndex
; /* fail */