Redundant test.
[p5sagit/p5-mst-13.2.git] / perlio.c
index ea36d80..2dc18b2 100644 (file)
--- a/perlio.c
+++ b/perlio.c
@@ -214,7 +214,7 @@ PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags)
        return NULL;
     }
     else {
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
     }
 #endif
     return NULL;
@@ -481,7 +481,7 @@ PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags)
        return new;
     }
     else {
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
        return NULL;
     }
 }
@@ -640,6 +640,36 @@ PerlIO_pop(pTHX_ PerlIO *f)
     }
 }
 
+/* Return as an array the stack of layers on a filehandle.  Note that
+ * the stack is returned top-first in the array, and there are three
+ * times as many array elements as there are layers in the stack: the
+ * first element of a layer triplet is the name, the second one is the
+ * arguments, and the third one is the flags. */
+
+AV *
+PerlIO_get_layers(pTHX_ PerlIO *f)
+{
+     AV *av = newAV();
+
+     if (PerlIOValid(f)) {
+          dSP;
+         PerlIOl *l = PerlIOBase(f);
+
+         while (l) {
+              SV *name = l->tab && l->tab->name ?
+                   newSVpv(l->tab->name, 0) : &PL_sv_undef;
+              SV *arg = l->tab && l->tab->Getarg ?
+                   (*l->tab->Getarg)(aTHX_ &l, 0, 0) : &PL_sv_undef;
+              av_push(av, name);
+              av_push(av, arg);
+              av_push(av, newSViv((IV)l->flags));
+              l = l->next;
+         }
+     }
+
+     return av;
+}
+
 /*--------------------------------------------------------------------------------------*/
 /*
  * XS Interface for perl code
@@ -660,15 +690,28 @@ PerlIO_find_layer(pTHX_ const char *name, STRLEN len, int load)
     }
     if (load && PL_subname && PL_def_layerlist
        && PL_def_layerlist->cur >= 2) {
-       SV *pkgsv = newSVpvn("PerlIO", 6);
-       SV *layer = newSVpvn(name, len);
-       ENTER;
-       /*
-        * The two SVs are magically freed by load_module
-        */
-       Perl_load_module(aTHX_ 0, pkgsv, Nullsv, layer, Nullsv);
-       LEAVE;
-       return PerlIO_find_layer(aTHX_ name, len, 0);
+       if (PL_in_load_module) {
+           Perl_croak(aTHX_ "Recursive call to Perl_load_module in PerlIO_find_layer");
+           return NULL;
+       } else {
+           SV *pkgsv = newSVpvn("PerlIO", 6);
+           SV *layer = newSVpvn(name, len);
+           CV *cv  = get_cv("PerlIO::Layer::NoWarnings", FALSE);
+           ENTER;
+           SAVEINT(PL_in_load_module);
+           if (cv) {
+               SAVESPTR(PL_warnhook);
+               PL_warnhook = (SV *) cv;
+           }
+           PL_in_load_module++;
+           /*
+            * The two SVs are magically freed by load_module
+            */
+           Perl_load_module(aTHX_ 0, pkgsv, Nullsv, layer, Nullsv);
+           PL_in_load_module--;
+           LEAVE;
+           return PerlIO_find_layer(aTHX_ name, len, 0);
+       }
     }
     PerlIO_debug("Cannot find %.*s\n", (int) len, name);
     return NULL;
@@ -762,6 +805,17 @@ PerlIO_tab_sv(pTHX_ PerlIO_funcs *tab)
     return sv;
 }
 
+XS(XS_PerlIO__Layer__NoWarnings)
+{
+    /* This is used as a %SIG{__WARN__} handler to supress warnings 
+       during loading of layers.
+     */
+    dXSARGS;
+    if (items)
+       PerlIO_debug("warning:%s\n",SvPV_nolen(ST(0)));
+    XSRETURN(0);
+}
+
 XS(XS_PerlIO__Layer__find)
 {
     dXSARGS;
@@ -812,7 +866,7 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names)
                        Perl_warner(aTHX_ packWARN(WARN_LAYER),
                              "perlio: invalid separator character %c%c%c in layer specification list %s",
                              q, *s, q, s);
-                   SETERRNO(EINVAL, LIB$_INVARG);
+                   SETERRNO(EINVAL, LIB_INVARG);
                    return -1;
                }
                do {
@@ -1004,6 +1058,7 @@ Perl_boot_core_PerlIO(pTHX)
          __FILE__);
 #endif
     newXS("PerlIO::Layer::find", XS_PerlIO__Layer__find, __FILE__);
+    newXS("PerlIO::Layer::NoWarnings", XS_PerlIO__Layer__NoWarnings, __FILE__);
 }
 
 PerlIO_funcs *
@@ -1223,7 +1278,7 @@ PerlIO__close(pTHX_ PerlIO *f)
     if (PerlIOValid(f))
        return (*PerlIOBase(f)->tab->Close) (aTHX_ f);
     else {
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
        return -1;
     }
 }
@@ -1247,7 +1302,7 @@ Perl_PerlIO_fileno(pTHX_ PerlIO *f)
     if (PerlIOValid(f))
        return (*PerlIOBase(f)->tab->Fileno) (aTHX_ f);
     else {
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
        return -1;
     }
 }
@@ -1448,7 +1503,7 @@ Perl_PerlIO_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
     if (PerlIOValid(f))
        return (*PerlIOBase(f)->tab->Read) (aTHX_ f, vbuf, count);
     else {
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
        return -1;
     }
 }
@@ -1459,7 +1514,7 @@ Perl_PerlIO_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
     if (PerlIOValid(f))
        return (*PerlIOBase(f)->tab->Unread) (aTHX_ f, vbuf, count);
     else {
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
        return -1;
     }
 }
@@ -1470,7 +1525,7 @@ Perl_PerlIO_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
     if (PerlIOValid(f))
        return (*PerlIOBase(f)->tab->Write) (aTHX_ f, vbuf, count);
     else {
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
        return -1;
     }
 }
@@ -1481,7 +1536,7 @@ Perl_PerlIO_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
     if (PerlIOValid(f))
        return (*PerlIOBase(f)->tab->Seek) (aTHX_ f, offset, whence);
     else {
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
        return -1;
     }
 }
@@ -1492,7 +1547,7 @@ Perl_PerlIO_tell(pTHX_ PerlIO *f)
     if (PerlIOValid(f))
        return (*PerlIOBase(f)->tab->Tell) (aTHX_ f);
     else {
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
        return -1;
     }
 }
@@ -1508,13 +1563,13 @@ Perl_PerlIO_flush(pTHX_ PerlIO *f)
            }
            else {
                PerlIO_debug("Cannot flush f=%p :%s\n", (void*)f, tab->name);
-               SETERRNO(EBADF, SS$_IVCHAN);
+               SETERRNO(EBADF, SS_IVCHAN);
                return -1;
            }
        }
        else {
            PerlIO_debug("Cannot flush f=%p\n", (void*)f);
-           SETERRNO(EBADF, SS$_IVCHAN);
+           SETERRNO(EBADF, SS_IVCHAN);
            return -1;
        }
     }
@@ -1566,7 +1621,7 @@ Perl_PerlIO_fill(pTHX_ PerlIO *f)
     if (PerlIOValid(f))
        return (*PerlIOBase(f)->tab->Fill) (aTHX_ f);
     else {
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
        return -1;
     }
 }
@@ -1577,7 +1632,7 @@ PerlIO_isutf8(PerlIO *f)
     if (PerlIOValid(f))
        return (PerlIOBase(f)->flags & PERLIO_F_UTF8) != 0;
     else {
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
        return -1;
     }
 }
@@ -1588,7 +1643,7 @@ Perl_PerlIO_eof(pTHX_ PerlIO *f)
     if (PerlIOValid(f))
        return (*PerlIOBase(f)->tab->Eof) (aTHX_ f);
     else {
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
        return -1;
     }
 }
@@ -1599,7 +1654,7 @@ Perl_PerlIO_error(pTHX_ PerlIO *f)
     if (PerlIOValid(f))
        return (*PerlIOBase(f)->tab->Error) (aTHX_ f);
     else {
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
        return -1;
     }
 }
@@ -1610,7 +1665,7 @@ Perl_PerlIO_clearerr(pTHX_ PerlIO *f)
     if (PerlIOValid(f))
        (*PerlIOBase(f)->tab->Clearerr) (aTHX_ f);
     else
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
 }
 
 void
@@ -1619,7 +1674,7 @@ Perl_PerlIO_setlinebuf(pTHX_ PerlIO *f)
     if (PerlIOValid(f))
        (*PerlIOBase(f)->tab->Setlinebuf) (aTHX_ f);
     else
-       SETERRNO(EBADF, SS$_IVCHAN);
+       SETERRNO(EBADF, SS_IVCHAN);
 }
 
 int
@@ -1907,7 +1962,7 @@ PerlIOBase_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
            l->flags |= PERLIO_F_TRUNCATE | PERLIO_F_CANWRITE;
            break;
        default:
-           SETERRNO(EINVAL, LIB$_INVARG);
+           SETERRNO(EINVAL, LIB_INVARG);
            return -1;
        }
        while (*mode) {
@@ -1922,7 +1977,7 @@ PerlIOBase_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
                l->flags |= PERLIO_F_CRLF;
                break;
            default:
-               SETERRNO(EINVAL, LIB$_INVARG);
+               SETERRNO(EINVAL, LIB_INVARG);
                return -1;
            }
        }
@@ -2233,7 +2288,7 @@ PerlIOUnix_oflags(const char *mode)
      */
     oflags |= O_BINARY;
     if (*mode || oflags == -1) {
-       SETERRNO(EINVAL, LIB$_INVARG);
+       SETERRNO(EINVAL, LIB_INVARG);
        oflags = -1;
     }
     return oflags;
@@ -2401,7 +2456,7 @@ PerlIOUnix_close(pTHX_ PerlIO *f)
        }
     }
     else {
-       SETERRNO(EBADF,SS$_IVCHAN);
+       SETERRNO(EBADF,SS_IVCHAN);
        return -1;
     }
     while (PerlLIO_close(fd) != 0) {
@@ -2654,11 +2709,13 @@ PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
      */
     if ((f = PerlIOBase_dup(aTHX_ f, o, param, flags))) {
        FILE *stdio = PerlIOSelf(o, PerlIOStdio)->stdio;
+       int fd = fileno(stdio);
+       char mode[8];
        if (flags & PERLIO_DUP_FD) {
-           int fd = PerlLIO_dup(fileno(stdio));
-           if (fd >= 0) {
-               char mode[8];
-               stdio = PerlSIO_fdopen(fd, PerlIO_modestr(o,mode));
+           int dfd = PerlLIO_dup(fileno(stdio));
+           if (dfd >= 0) {
+               stdio = PerlSIO_fdopen(dfd, PerlIO_modestr(o,mode));
+               goto set_this;
            }
            else {
                /* FIXME: To avoid messy error recovery if dup fails
@@ -2666,62 +2723,198 @@ PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
                 */
            }
        }
+       stdio = PerlSIO_fdopen(fd, PerlIO_modestr(o,mode));
+    set_this:
        PerlIOSelf(f, PerlIOStdio)->stdio = stdio;
        PerlIOUnix_refcnt_inc(fileno(stdio));
     }
     return f;
 }
 
+static int
+PerlIOStdio_invalidate_fileno(pTHX_ FILE *f)
+{
+    /* XXX this could use PerlIO_canset_fileno() and
+     * PerlIO_set_fileno() support from Configure 
+     */
+#  if defined(__GLIBC__)
+    /* There may be a better way for GLIBC:
+       - libio.h defines a flag to not close() on cleanup 
+     */        
+    f->_fileno = -1;
+    return 1;
+#  elif defined(__sun__)
+#    if defined(_LP64)
+    /* On solaris, if _LP64 is defined, the FILE structure is this:
+     *
+     *  struct FILE {
+     *      long __pad[16];
+     *  };
+     *
+     * It turns out that the fd is stored in the top 32 bits of 
+     * file->__pad[4]. The lower 32 bits contain flags. file->pad[5] appears
+     * to contain a pointer or offset into another structure. All the
+     * remaining fields are zero.
+     *
+     * We set the top bits to -1 (0xFFFFFFFF).
+     */
+    f->__pad[4] |= 0xffffffff00000000L;
+    assert(fileno(f) == 0xffffffff);
+#    else /* !defined(_LP64) */
+    /* _file is just a unsigned char :-( 
+       Not clear why we dup() rather than using -1 
+       even if that would be treated as 0xFF - so will 
+       a dup fail ...
+     */
+    f->_file = PerlLIO_dup(fileno(f));
+#    endif /* defined(_LP64) */
+    return 1;
+#  elif defined(__hpux)
+    f->__fileH = 0xff;
+    f->__fileL = 0xff;
+    return 1;
+   /* Next one ->_file seems to be a reasonable fallback, i.e. if
+      your platform does not have special entry try this one.       
+      [For OSF only have confirmation for Tru64 (alpha)
+      but assume other OSFs will be similar.]
+    */    
+#  elif defined(_AIX) || defined(__osf__) || defined(__irix__)
+    f->_file = -1;
+    return 1;
+#  elif defined(__FreeBSD__)
+    /* There may be a better way on FreeBSD:
+        - we could insert a dummy func in the _close function entry 
+       f->_close = (int (*)(void *)) dummy_close; 
+     */
+    f->_file = -1;
+    return 1;
+#  elif defined(__CYGWIN__)
+    /* There may be a better way on CYGWIN:
+        - we could insert a dummy func in the _close function entry 
+       f->_close = (int (*)(void *)) dummy_close; 
+     */
+    f->_file = -1;
+    return 1;
+#  elif defined(WIN32)
+#    if defined(__BORLANDC__)
+    f->fd = PerlLIO_dup(fileno(f));
+#    elif defined(UNDER_CE)
+    /* WIN_CE does not have access to FILE internals, it hardly has FILE
+       structure at all
+     */
+#    else
+    f->_file = -1;
+#    endif
+    return 1;
+#  else
+#if 0
+    /* Sarathy's code did this - we fall back to a dup/dup2 hack 
+       (which isn't thread safe) instead
+     */  
+#    error "Don't know how to set FILE.fileno on your platform"
+#endif
+    return 0;
+#  endif
+}
+
 IV
 PerlIOStdio_close(pTHX_ PerlIO *f)
 {
-#ifdef SOCKS5_VERSION_NAME
-    int optval;
-    Sock_size_t optlen = sizeof(int);
-#endif
     FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
     if (!stdio) {
        errno = EBADF;
        return -1;
     }
-    if (PerlIOUnix_refcnt_dec(fileno(stdio)) > 0) {
-       /* Do not close it but do flush any buffers */
-       return PerlIO_flush(f);
-    }
-    return (
+    else {
+        int fd = fileno(stdio);
+       int socksfd = 0;
+       int invalidate = 0;
+       IV result = 0;
+       int saveerr = 0;
+       int dupfd = 0;
 #ifdef SOCKS5_VERSION_NAME
-              (getsockopt
-               (PerlIO_fileno(f), SOL_SOCKET, SO_TYPE, (void *) &optval,
-                &optlen) <
-               0) ? PerlSIO_fclose(stdio) : close(PerlIO_fileno(f))
-#else
-              PerlSIO_fclose(stdio)
+       /* Socks lib overrides close() but stdio isn't linked to 
+          that library (though we are) - so we must call close() 
+          on sockets on stdio's behalf. 
+        */   
+       int optval;
+       Sock_size_t optlen = sizeof(int);
+       if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *) &optval, &optlen) == 0) {
+            socksfd = 1;
+           invalidate = 1;  
+       }
 #endif
-       );
-
+       if (PerlIOUnix_refcnt_dec(fd) > 0) {
+           /* File descriptor still in use */
+           invalidate = 1;
+           socksfd = 0;
+       }    
+       if (invalidate) {
+           /* For STD* handles don't close the stdio at all 
+              this is because we have shared the FILE * too 
+            */
+           if (stdio == stdin) {
+               /* Some stdios are buggy fflush-ing inputs */
+               return 0;
+           }
+           else if (stdio == stdout || stdio == stderr) {
+               return PerlIO_flush(f);
+           }
+            /* Tricky - must fclose(stdio) to free memory but not close(fd) 
+              Use Sarathy's trick from maint-5.6 to invalidate the 
+              fileno slot of the FILE * 
+           */ 
+           result = PerlIO_flush(f);
+           saveerr = errno;
+           if (!(invalidate = PerlIOStdio_invalidate_fileno(aTHX_ stdio))) {
+               dupfd = PerlLIO_dup(fd);
+           }
+       } 
+        result = PerlSIO_fclose(stdio);
+       /* We treat error from stdio as success if we invalidated 
+          errno may NOT be expected EBADF 
+        */
+       if (invalidate && result != 0) {
+           errno = saveerr;
+           result = 0;
+       } 
+       if (socksfd) {
+           /* in SOCKS case let close() determine return value */
+           result = close(fd);
+       }
+       if (dupfd) {
+           PerlLIO_dup2(dupfd,fd);
+           close(dupfd);
+       }
+       return result;
+    } 
 }
 
-
-
 SSize_t
 PerlIOStdio_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
 {
     FILE *s = PerlIOSelf(f, PerlIOStdio)->stdio;
     SSize_t got = 0;
-    if (count == 1) {
-       STDCHAR *buf = (STDCHAR *) vbuf;
-       /*
-        * Perl is expecting PerlIO_getc() to fill the buffer Linux's
-        * stdio does not do that for fread()
-        */
-       int ch = PerlSIO_fgetc(s);
-       if (ch != EOF) {
-           *buf = ch;
-           got = 1;
+    for (;;) {
+       if (count == 1) {
+           STDCHAR *buf = (STDCHAR *) vbuf;
+           /*
+            * Perl is expecting PerlIO_getc() to fill the buffer Linux's
+            * stdio does not do that for fread()
+            */
+           int ch = PerlSIO_fgetc(s);
+           if (ch != EOF) {
+               *buf = ch;
+               got = 1;
+           }
        }
+       else
+           got = PerlSIO_fread(vbuf, 1, count, s);
+       if (got || errno != EINTR)
+           break;
+       PERL_ASYNC_CHECK();
+       errno = 0;      /* just in case */
     }
-    else
-       got = PerlSIO_fread(vbuf, 1, count, s);
     return got;
 }
 
@@ -2786,8 +2979,16 @@ PerlIOStdio_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
 SSize_t
 PerlIOStdio_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
 {
-    return PerlSIO_fwrite(vbuf, 1, count,
-                         PerlIOSelf(f, PerlIOStdio)->stdio);
+    SSize_t got;
+    for (;;) {
+       got = PerlSIO_fwrite(vbuf, 1, count,
+                             PerlIOSelf(f, PerlIOStdio)->stdio);
+       if (got || errno != EINTR)
+           break;
+       PERL_ASYNC_CHECK();
+       errno = 0;      /* just in case */
+    }
+    return got;
 }
 
 IV
@@ -3172,7 +3373,7 @@ PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
 #ifdef PERLIO_USING_CRLF
 #  ifdef PERLIO_IS_BINMODE_FD
                if (PERLIO_IS_BINMODE_FD(fd))
-                   PerlIO_binmode(f,  '<'/*not used*/, O_BINARY, Nullch);
+                   PerlIO_binmode(aTHX_ f,  '<'/*not used*/, O_BINARY, Nullch);
                else
 #  endif
                /*
@@ -3395,6 +3596,11 @@ PerlIOBuf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
        PerlIO_get_base(f);
     if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE))
        return 0;
+    if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
+       if (PerlIO_flush(f) != 0) {
+           return 0;
+       }
+    }  
     while (count > 0) {
        SSize_t avail = b->bufsiz - (b->ptr - b->buf);
        if ((SSize_t) count < avail)
@@ -3453,6 +3659,19 @@ PerlIOBuf_tell(pTHX_ PerlIO *f)
      * b->posn is file position where b->buf was read, or will be written
      */
     Off_t posn = b->posn;
+    if ((PerlIOBase(f)->flags & PERLIO_F_APPEND) && 
+        (PerlIOBase(f)->flags & PERLIO_F_WRBUF)) {
+#if 1
+       /* As O_APPEND files are normally shared in some sense it is better
+          to flush :
+        */     
+       PerlIO_flush(f);
+#else  
+        /* when file is NOT shared then this is sufficient */ 
+       PerlIO_seek(PerlIONext(f),0, SEEK_END);
+#endif
+       posn = b->posn = PerlIO_tell(PerlIONext(f));
+    }
     if (b->buf) {
        /*
         * If buffer is valid adjust position by amount in buffer
@@ -4064,7 +4283,7 @@ PerlIOMmap_map(pTHX_ PerlIO *f)
                if (!page_size) {
 #if defined(HAS_SYSCONF) && (defined(_SC_PAGESIZE) || defined(_SC_PAGE_SIZE))
                    {
-                       SETERRNO(0, SS$_NORMAL);
+                       SETERRNO(0, SS_NORMAL);
 #   ifdef _SC_PAGESIZE
                        page_size = sysconf(_SC_PAGESIZE);
 #   else
@@ -4583,7 +4802,7 @@ PerlIO_setpos(PerlIO *f, SV *pos)
        if (f && len == sizeof(Off_t))
            return PerlIO_seek(f, *posn, SEEK_SET);
     }
-    SETERRNO(EINVAL, SS$_IVCHAN);
+    SETERRNO(EINVAL, SS_IVCHAN);
     return -1;
 }
 #else
@@ -4603,7 +4822,7 @@ PerlIO_setpos(PerlIO *f, SV *pos)
 #endif
        }
     }
-    SETERRNO(EINVAL, SS$_IVCHAN);
+    SETERRNO(EINVAL, SS_IVCHAN);
     return -1;
 }
 #endif