		/*    doio.c
		 *
		 *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
		 *    2000, 2001, 2002, 2003, 2004, 2005, by Larry Wall and others
		 *
		 *    You may distribute under the terms of either the GNU General Public
		 *    License or the Artistic License, as specified in the README file.
		 *
		 */
		
		/*
		 * "Far below them they saw the white waters pour into a foaming bowl, and
		 * then swirl darkly about a deep oval basin in the rocks, until they found
		 * their way out again through a narrow gate, and flowed away, fuming and
		 * chattering, into calmer and more level reaches."
		 */
		
		/* This file contains functions that do the actual I/O on behalf of ops.
		 * For example, pp_print() calls the do_print() function in this file for
		 * each argument needing printing.
		 */
		
		#include "EXTERN.h"
		#define PERL_IN_DOIO_C
		#include "perl.h"
		
		#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
		#ifndef HAS_SEM
		#include <sys/ipc.h>
		#endif
		#ifdef HAS_MSG
		#include <sys/msg.h>
		#endif
		#ifdef HAS_SHM
		#include <sys/shm.h>
		# ifndef HAS_SHMAT_PROTOTYPE
		    extern Shmat_t shmat (int, char *, int);
		# endif
		#endif
		#endif
		
		#ifdef I_UTIME
		#  if defined(_MSC_VER) || defined(__MINGW32__)
		#    include <sys/utime.h>
		#  else
		#    include <utime.h>
		#  endif
		#endif
		
		#ifdef O_EXCL
		#  define OPEN_EXCL O_EXCL
		#else
		#  define OPEN_EXCL 0
		#endif
		
		#define PERL_MODE_MAX 8
		#define PERL_FLAGS_MAX 10
		
		#include <signal.h>
		
		bool
		Perl_do_open(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
			     int rawmode, int rawperm, PerlIO *supplied_fp)
        3134    {
        3134        return do_openn(gv, name, len, as_raw, rawmode, rawperm,
				    supplied_fp, (SV **) NULL, 0);
		}
		
		bool
		Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
			      int rawmode, int rawperm, PerlIO *supplied_fp, SV *svs,
			      I32 num_svs)
      ######    {
      ######        (void)num_svs;
      ######        return do_openn(gv, name, len, as_raw, rawmode, rawperm,
				    supplied_fp, &svs, 1);
		}
		
		bool
		Perl_do_openn(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
			      int rawmode, int rawperm, PerlIO *supplied_fp, SV **svp,
			      I32 num_svs)
       21971    {
		    dVAR;
       21971        register IO *io = GvIOn(gv);
       21971        PerlIO *saveifp = Nullfp;
       21971        PerlIO *saveofp = Nullfp;
       21971        int savefd = -1;
       21971        char savetype = IoTYPE_CLOSED;
       21971        int writing = 0;
       21971        PerlIO *fp;
       21971        int fd;
       21971        int result;
       21971        bool was_fdopen = FALSE;
       21971        bool in_raw = 0, in_crlf = 0, out_raw = 0, out_crlf = 0;
       21971        char *type  = NULL;
       21971        char mode[PERL_MODE_MAX];	/* stdio file mode ("r\0", "rb\0", "r+b\0" etc.) */
       21971        SV *namesv;
		
       21971        Zero(mode,sizeof(mode),char);
       21971        PL_forkprocess = 1;		/* assume true if no fork */
		
		    /* Collect default raw/crlf info from the op */
       21971        if (PL_op && PL_op->op_type == OP_OPEN) {
			/* set up IO layers */
       18837    	const U8 flags = PL_op->op_private;
       18837    	in_raw = (flags & OPpOPEN_IN_RAW);
       18837    	in_crlf = (flags & OPpOPEN_IN_CRLF);
       18837    	out_raw = (flags & OPpOPEN_OUT_RAW);
       18837    	out_crlf = (flags & OPpOPEN_OUT_CRLF);
		    }
		
		    /* If currently open - close before we re-open */
       21971        if (IoIFP(io)) {
        1134    	fd = PerlIO_fileno(IoIFP(io));
        1134    	if (IoTYPE(io) == IoTYPE_STD) {
			    /* This is a clone of one of STD* handles */
           1    	    result = 0;
			}
        1133    	else if (fd >= 0 && fd <= PL_maxsysfd) {
			    /* This is one of the original STD* handles */
         759    	    saveifp  = IoIFP(io);
         759    	    saveofp  = IoOFP(io);
         759    	    savetype = IoTYPE(io);
         759    	    savefd   = fd;
         759    	    result   = 0;
			}
         374    	else if (IoTYPE(io) == IoTYPE_PIPE)
           3    	    result = PerlProc_pclose(IoIFP(io));
         371    	else if (IoIFP(io) != IoOFP(io)) {
         148    	    if (IoOFP(io)) {
           3    		result = PerlIO_close(IoOFP(io));
           3    		PerlIO_close(IoIFP(io)); /* clear stdio, fd already closed */
			    }
			    else
         145    		result = PerlIO_close(IoIFP(io));
			}
			else
         223    	    result = PerlIO_close(IoIFP(io));
        1134    	if (result == EOF && fd > PL_maxsysfd) {
			    /* Why is this not Perl_warn*() call ? */
      ######    	    PerlIO_printf(Perl_error_log,
					  "Warning: unable to close filehandle %s properly.\n",
					  GvENAME(gv));
			}
        1134    	IoOFP(io) = IoIFP(io) = Nullfp;
		    }
		
       21971        if (as_raw) {
		        /* sysopen style args, i.e. integer mode and permissions */
        3068    	STRLEN ix = 0;
        3068    	const int appendtrunc =
			     0
		#ifdef O_APPEND	/* Not fully portable. */
			     |O_APPEND
		#endif
		#ifdef O_TRUNC	/* Not fully portable. */
			     |O_TRUNC
		#endif
        3068    	     ;
        3068    	const int modifyingmode = O_WRONLY|O_RDWR|O_CREAT|appendtrunc;
        3068    	int ismodifying;
		
        3068    	if (num_svs != 0) {
      ######    	     Perl_croak(aTHX_ "panic: sysopen with multiple args");
			}
			/* It's not always
		
			   O_RDONLY 0
			   O_WRONLY 1
			   O_RDWR   2
		
			   It might be (in OS/390 and Mac OS Classic it is)
		
			   O_WRONLY 1
			   O_RDONLY 2
			   O_RDWR   3
		
			   This means that simple & with O_RDWR would look
			   like O_RDONLY is present.  Therefore we have to
			   be more careful.
			*/
        3068    	if ((ismodifying = (rawmode & modifyingmode))) {
        3040    	     if ((ismodifying & O_WRONLY) == O_WRONLY ||
				 (ismodifying & O_RDWR)   == O_RDWR   ||
				 (ismodifying & (O_CREAT|appendtrunc)))
        3040    		  TAINT_PROPER("sysopen");
			}
        3053    	mode[ix++] = IoTYPE_NUMERIC; /* Marker to openn to use numeric "sysopen" */
		
		#if defined(USE_64_BIT_RAWIO) && defined(O_LARGEFILE)
        3053    	rawmode |= O_LARGEFILE;	/* Transparently largefiley. */
		#endif
		
        3053            IoTYPE(io) = PerlIO_intmode2str(rawmode, &mode[ix], &writing);
		
        3053    	namesv = sv_2mortal(newSVpvn(name,strlen(name)));
        3053    	num_svs = 1;
        3053    	svp = &namesv;
        3053            type = Nullch;
        3053    	fp = PerlIO_openn(aTHX_ type, mode, -1, rawmode, rawperm, NULL, num_svs, svp);
		    }
		    else {
			/* Regular (non-sys) open */
       18903    	char *oname = name;
       18903    	STRLEN olen = len;
       18903    	char *tend;
       18903    	int dodup = 0;
       18903    	PerlIO *that_fp = NULL;
		
       18903    	type = savepvn(name, len);
       18903    	tend = type+len;
       18903    	SAVEFREEPV(type);
		
		        /* Lose leading and trailing white space */
       18920            for (; isSPACE(*type); type++) ;
       18919            while (tend > type && isSPACE(tend[-1]))
          16    	    *--tend = '\0';
		
       18903    	if (num_svs) {
			    /* New style explicit name, type is just mode and layer info */
		#ifdef USE_STDIO
			    if (SvROK(*svp) && !strchr(name,'&')) {
				if (ckWARN(WARN_IO))
				    Perl_warner(aTHX_ packWARN(WARN_IO),
					    "Can't open a reference");
				SETERRNO(EINVAL, LIB_INVARG);
				goto say_false;
			    }
		#endif /* USE_STDIO */
        1254    	    name = SvOK(*svp) ? savesvpv (*svp) : savepvn ("", 0);
        1254    	    SAVEFREEPV(name);
			}
			else {
       17649    	    name = type;
       17649    	    len  = tend-type;
			}
       18903    	IoTYPE(io) = *type;
       18903    	if ((*type == IoTYPE_RDWR) && /* scary */
		           (*(type+1) == IoTYPE_RDONLY || *(type+1) == IoTYPE_WRONLY) &&
			    ((!num_svs || (tend > type+1 && tend[-1] != IoTYPE_PIPE)))) {
          37    	    TAINT_PROPER("open");
          37    	    mode[1] = *type++;
          37    	    writing = 1;
			}
		
       18903    	if (*type == IoTYPE_PIPE) {
          40    	    if (num_svs) {
           2    		if (type[1] != IoTYPE_STD) {
			          unknown_open_mode:
           4    		    Perl_croak(aTHX_ "Unknown open() mode '%.*s'", (int)olen, oname);
				}
           2    		type++;
			    }
          40    	    for (type++; isSPACE(*type); type++) ;
          40    	    if (!num_svs) {
          38    		name = type;
          38    		len = tend-type;
			    }
          40    	    if (*name == '\0') {
				/* command is missing 19990114 */
           6    		if (ckWARN(WARN_PIPE))
           2    		    Perl_warner(aTHX_ packWARN(WARN_PIPE), "Missing command in piped open");
           6    		errno = EPIPE;
           6    		goto say_false;
			    }
          34    	    if ((*name == '-' && name[1] == '\0') || num_svs)
          23    		TAINT_ENV();
          34    	    TAINT_PROPER("piped open");
          33    	    if (!num_svs && name[len-1] == '|') {
           2    		name[--len] = '\0' ;
           2    		if (ckWARN(WARN_PIPE))
           1    		    Perl_warner(aTHX_ packWARN(WARN_PIPE), "Can't open bidirectional pipe");
			    }
          33    	    mode[0] = 'w';
          33    	    writing = 1;
		#ifdef HAS_STRLCAT
		            if (out_raw)
		                strlcat(mode, "b", PERL_MODE_MAX);
		            else if (out_crlf)
		                strlcat(mode, "t", PERL_MODE_MAX); 
		#else
          33    	    if (out_raw)
      ######    		strcat(mode, "b");
          33    	    else if (out_crlf)
      ######    		strcat(mode, "t");
		#endif
          33    	    if (num_svs > 1) {
      ######    		fp = PerlProc_popen_list(mode, num_svs, svp);
			    }
			    else {
          33    		fp = PerlProc_popen(name,mode);
			    }
          54    	    if (num_svs) {
           2    		if (*type) {
      ######    		    if (PerlIO_apply_layers(aTHX_ fp, mode, type) != 0) {
      ######    			goto say_false;
				    }
				}
			    }
			} /* IoTYPE_PIPE */
       18863    	else if (*type == IoTYPE_WRONLY) {
        8886    	    TAINT_PROPER("open");
        8885    	    type++;
        8885    	    if (*type == IoTYPE_WRONLY) {
				/* Two IoTYPE_WRONLYs in a row make for an IoTYPE_APPEND. */
          40    		mode[0] = IoTYPE(io) = IoTYPE_APPEND;
          40    		type++;
			    }
			    else {
        8845    		mode[0] = 'w';
			    }
        8885    	    writing = 1;
		
		#ifdef HAS_STRLCAT
		            if (out_raw)
		                strlcat(mode, "b", PERL_MODE_MAX);
		            else if (out_crlf)
		                strlcat(mode, "t", PERL_MODE_MAX);
		#else
        8885    	    if (out_raw)
      ######    		strcat(mode, "b");
        8885    	    else if (out_crlf)
      ######    		strcat(mode, "t");
		#endif
        8885    	    if (*type == '&') {
			      duplicity:
        1531    		dodup = PERLIO_DUP_FD;
        1531    		type++;
        1531    		if (*type == '=') {
          28    		    dodup = 0;
          28    		    type++;
				}
        1531    		if (!num_svs && !*type && supplied_fp) {
				    /* "<+&" etc. is used by typemaps */
          17    		    fp = supplied_fp;
				}
				else {
        1514    		    if (num_svs > 1) {
      ######    			Perl_croak(aTHX_ "More than one argument to '%c&' open",IoTYPE(io));
				    }
        1514    		    for (; isSPACE(*type); type++) ;
        1514    		    if (num_svs && (SvIOK(*svp) || (SvPOK(*svp) && looks_like_number(*svp)))) {
           5    			fd = SvUV(*svp);
           5    			num_svs = 0;
				    }
        1509    		    else if (isDIGIT(*type)) {
          23    			fd = atoi(type);
				    }
				    else {
        1486    			const IO* thatio;
        1486    			if (num_svs) {
           8    			    thatio = sv_2io(*svp);
					}
					else {
        1478    			    GV *thatgv;
        1478    			    thatgv = gv_fetchpv(type,FALSE,SVt_PVIO);
        1478    			    thatio = GvIO(thatgv);
					}
        1484    			if (!thatio) {
		#ifdef EINVAL
           1    			    SETERRNO(EINVAL,SS_IVCHAN);
		#endif
           1    			    goto say_false;
					}
        1483    			if ((that_fp = IoIFP(thatio))) {
					    /* Flush stdio buffer before dup. --mjd
					     * Unfortunately SEEK_CURing 0 seems to
					     * be optimized away on most platforms;
					     * only Solaris and Linux seem to flush
					     * on that. --jhi */
		#ifdef USE_SFIO
					    /* sfio fails to clear error on next
					       sfwrite, contrary to documentation.
					       -- Nick Clark */
					    if (PerlIO_seek(that_fp, 0, SEEK_CUR) == -1)
						PerlIO_clearerr(that_fp);
		#endif
					    /* On the other hand, do all platforms
					     * take gracefully to flushing a read-only
					     * filehandle?  Perhaps we should do
					     * fsetpos(src)+fgetpos(dst)?  --nik */
        1483    			    PerlIO_flush(that_fp);
        1483    			    fd = PerlIO_fileno(that_fp);
					    /* When dup()ing STDIN, STDOUT or STDERR
					     * explicitly set appropriate access mode */
        1483    			    if (that_fp == PerlIO_stdout()
						|| that_fp == PerlIO_stderr())
        1297    			        IoTYPE(io) = IoTYPE_WRONLY;
         186    			    else if (that_fp == PerlIO_stdin())
           1                                    IoTYPE(io) = IoTYPE_RDONLY;
					    /* When dup()ing a socket, say result is
					     * one as well */
         185    			    else if (IoTYPE(thatio) == IoTYPE_SOCKET)
      ######    				IoTYPE(io) = IoTYPE_SOCKET;
					}
					else
      ######    			    fd = -1;
				    }
        1511    		    if (!num_svs)
        1505    			type = Nullch;
        1511    		    if (that_fp) {
        1483    			fp = PerlIO_fdupopen(aTHX_ that_fp, NULL, dodup);
				    }
				    else {
          28    			if (dodup)
           5    			    fd = PerlLIO_dup(fd);
					else
          23    			    was_fdopen = TRUE;
          28    			if (!(fp = PerlIO_openn(aTHX_ type,mode,fd,0,0,NULL,num_svs,svp))) {
      ######    			    if (dodup)
      ######    				PerlLIO_close(fd);
					}
				    }
				}
			    } /* & */
			    else {
       10686    		for (; isSPACE(*type); type++) ;
        7374    		if (*type == IoTYPE_STD && (!type[1] || isSPACE(type[1]) || type[1] == ':')) {
           1    		    type++;
           1    		    fp = PerlIO_stdout();
           1    		    IoTYPE(io) = IoTYPE_STD;
           1    		    if (num_svs > 1) {
      ######    			Perl_croak(aTHX_ "More than one argument to '>%c' open",IoTYPE_STD);
				    }
				}
				else  {
        7373    		    if (!num_svs) {
        6277    			namesv = sv_2mortal(newSVpvn(type,strlen(type)));
        6277    			num_svs = 1;
        6277    			svp = &namesv;
        6277    		        type = Nullch;
				    }
        7373    		    fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,num_svs,svp);
				}
			    } /* !& */
        8902    	    if (!fp && type && *type && *type != ':' && !isIDFIRST(*type))
           1    	       goto unknown_open_mode;
			} /* IoTYPE_WRONLY */
        9977    	else if (*type == IoTYPE_RDONLY) {
        4726    	    for (type++; isSPACE(*type); type++) ;
        4726    	    mode[0] = 'r';
		#ifdef HAS_STRLCAT
		            if (in_raw)
		                strlcat(mode, "b", PERL_MODE_MAX);
		            else if (in_crlf)
		                strlcat(mode, "t", PERL_MODE_MAX);
		#else
        4726    	    if (in_raw)
      ######    		strcat(mode, "b");
        4726    	    else if (in_crlf)
      ######    		strcat(mode, "t");
		#endif
        4726    	    if (*type == '&') {
          20    		goto duplicity;
			    }
        4706    	    if (*type == IoTYPE_STD && (!type[1] || isSPACE(type[1]) || type[1] == ':')) {
      ######    		type++;
      ######    		fp = PerlIO_stdin();
      ######    		IoTYPE(io) = IoTYPE_STD;
      ######    		if (num_svs > 1) {
      ######    		    Perl_croak(aTHX_ "More than one argument to '<%c' open",IoTYPE_STD);
				}
			    }
			    else {
        4706    		if (!num_svs) {
        4570    		    namesv = sv_2mortal(newSVpvn(type,strlen(type)));
        4570    		    num_svs = 1;
        4570    		    svp = &namesv;
        4570    		    type = Nullch;
				}
        4706    		fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,num_svs,svp);
			    }
        4706    	    if (!fp && type && *type && *type != ':' && !isIDFIRST(*type))
      ######    	       goto unknown_open_mode;
			} /* IoTYPE_RDONLY */
        5251    	else if ((num_svs && /* '-|...' or '...|' */
				  type[0] == IoTYPE_STD && type[1] == IoTYPE_PIPE) ||
			         (!num_svs && tend > type+1 && tend[-1] == IoTYPE_PIPE)) {
        1144    	    if (num_svs) {
           4    		type += 2;   /* skip over '-|' */
			    }
			    else {
        1140    		*--tend = '\0';
        1185    		while (tend > type && isSPACE(tend[-1]))
          45    		    *--tend = '\0';
        1140    		for (; isSPACE(*type); type++)
				    ;
        1140    		name = type;
        1140    	        len  = tend-type;
			    }
        1144    	    if (*name == '\0') {
				/* command is missing 19990114 */
      ######    		if (ckWARN(WARN_PIPE))
      ######    		    Perl_warner(aTHX_ packWARN(WARN_PIPE), "Missing command in piped open");
      ######    		errno = EPIPE;
      ######    		goto say_false;
			    }
        1144    	    if (!(*name == '-' && name[1] == '\0') || num_svs)
        1142    		TAINT_ENV();
        1144    	    TAINT_PROPER("piped open");
        1143    	    mode[0] = 'r';
		
		#ifdef HAS_STRLCAT
		            if (in_raw)
		                strlcat(mode, "b", PERL_MODE_MAX);
		            else if (in_crlf)
		                strlcat(mode, "t", PERL_MODE_MAX);
		#else
        1143    	    if (in_raw)
      ######    		strcat(mode, "b");
        1143    	    else if (in_crlf)
      ######    		strcat(mode, "t");
		#endif
		
        1143    	    if (num_svs > 1) {
      ######    		fp = PerlProc_popen_list(mode,num_svs,svp);
			    }
			    else {
        1143    		fp = PerlProc_popen(name,mode);
			    }
        1145    	    IoTYPE(io) = IoTYPE_PIPE;
        1145    	    if (num_svs) {
           4    		for (; isSPACE(*type); type++) ;
           4    		if (*type) {
      ######    		    if (PerlIO_apply_layers(aTHX_ fp, mode, type) != 0) {
      ######    			goto say_false;
				    }
				}
			    }
			}
			else { /* layer(Args) */
        4107    	    if (num_svs)
           3    		goto unknown_open_mode;
        4104    	    name = type;
        4104    	    IoTYPE(io) = IoTYPE_RDONLY;
        4104    	    for (; isSPACE(*name); name++)
				;
        4104    	    mode[0] = 'r';
		
		#ifdef HAS_STRLCAT
		            if (in_raw)
		                strlcat(mode, "b", PERL_MODE_MAX);
		            else if (in_crlf)
		                strlcat(mode, "t", PERL_MODE_MAX);
		#else
        4104    	    if (in_raw)
      ######    		strcat(mode, "b");
        4104    	    else if (in_crlf)
      ######    		strcat(mode, "t");
		#endif
		
        4104    	    if (*name == '-' && name[1] == '\0') {
          20    		fp = PerlIO_stdin();
          20    		IoTYPE(io) = IoTYPE_STD;
			    }
			    else {
        4084    		if (!num_svs) {
        4084    		    namesv = sv_2mortal(newSVpvn(type,strlen(type)));
        4084    		    num_svs = 1;
        4084    		    svp = &namesv;
        4084    		    type = Nullch;
				}
        4084    		fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,num_svs,svp);
			    }
			}
		    }
       21963        if (!fp) {
         727    	if (ckWARN(WARN_NEWLINE) && IoTYPE(io) == IoTYPE_RDONLY && strchr(name, '\n'))
           3    	    Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "open");
           3    	goto say_false;
		    }
		
       21236        if (ckWARN(WARN_IO)) {
        3712    	if ((IoTYPE(io) == IoTYPE_RDONLY) &&
			    (fp == PerlIO_stdout() || fp == PerlIO_stderr())) {
           2    		Perl_warner(aTHX_ packWARN(WARN_IO),
					    "Filehandle STD%s reopened as %s only for input",
					    ((fp == PerlIO_stdout()) ? "OUT" : "ERR"),
					    GvENAME(gv));
			}
        3710    	else if ((IoTYPE(io) == IoTYPE_WRONLY) && fp == PerlIO_stdin()) {
           1    		Perl_warner(aTHX_ packWARN(WARN_IO),
					    "Filehandle STDIN reopened as %s only for output",
					    GvENAME(gv));
			}
		    }
		
       21236        fd = PerlIO_fileno(fp);
		    /* If there is no fd (e.g. PerlIO::scalar) assume it isn't a
		     * socket - this covers PerlIO::scalar - otherwise unless we "know" the
		     * type probe for socket-ness.
		     */
       21236        if (IoTYPE(io) && IoTYPE(io) != IoTYPE_PIPE && IoTYPE(io) != IoTYPE_STD && fd >= 0) {
       19102    	if (PerlLIO_fstat(fd,&PL_statbuf) < 0) {
			    /* If PerlIO claims to have fd we had better be able to fstat() it. */
      ######    	    (void) PerlIO_close(fp);
      ######    	    goto say_false;
			}
		#ifndef PERL_MICRO
       19102    	if (S_ISSOCK(PL_statbuf.st_mode))
      ######    	    IoTYPE(io) = IoTYPE_SOCKET;	/* in case a socket was passed in to us */
		#ifdef HAS_SOCKET
       19102    	else if (
		#ifdef S_IFMT
			    !(PL_statbuf.st_mode & S_IFMT)
		#else
			    !PL_statbuf.st_mode
		#endif
			    && IoTYPE(io) != IoTYPE_WRONLY  /* Dups of STD* filehandles already have */
			    && IoTYPE(io) != IoTYPE_RDONLY  /* type so they aren't marked as sockets */
			) {				    /* on OS's that return 0 on fstat()ed pipe */
      ######    	     char tmpbuf[256];
      ######    	     Sock_size_t buflen = sizeof tmpbuf;
      ######    	     if (PerlSock_getsockname(fd, (struct sockaddr *)tmpbuf, &buflen) >= 0
				      || errno != ENOTSOCK)
      ######    		    IoTYPE(io) = IoTYPE_SOCKET; /* some OS's return 0 on fstat()ed socket */
						                /* but some return 0 for streams too, sigh */
			}
		#endif /* HAS_SOCKET */
		#endif /* !PERL_MICRO */
		    }
		
		    /* Eeek - FIXME !!!
		     * If this is a standard handle we discard all the layer stuff
		     * and just dup the fd into whatever was on the handle before !
		     */
		
       21236        if (saveifp) {		/* must use old fp? */
		        /* If fd is less that PL_maxsysfd i.e. STDIN..STDERR
		           then dup the new fileno down
		         */
         758    	if (saveofp) {
         743    	    PerlIO_flush(saveofp);	/* emulate PerlIO_close() */
         743    	    if (saveofp != saveifp) {	/* was a socket? */
          26    		PerlIO_close(saveofp);
			    }
			}
         758    	if (savefd != fd) {
			    /* Still a small can-of-worms here if (say) PerlIO::scalar
			       is assigned to (say) STDOUT - for now let dup2() fail
			       and provide the error
			     */
         758    	    if (PerlLIO_dup2(fd, savefd) < 0) {
           2    		(void)PerlIO_close(fp);
           2    		goto say_false;
			    }
		#ifdef VMS
			    if (savefd != PerlIO_fileno(PerlIO_stdin())) {
		                char newname[FILENAME_MAX+1];
		                if (PerlIO_getname(fp, newname)) {
		                    if (fd == PerlIO_fileno(PerlIO_stdout()))
		                        Perl_vmssetuserlnm(aTHX_ "SYS$OUTPUT", newname);
		                    if (fd == PerlIO_fileno(PerlIO_stderr()))
		                        Perl_vmssetuserlnm(aTHX_ "SYS$ERROR",  newname);
		                }
			    }
		#endif
		
		#if !defined(WIN32)
		           /* PL_fdpid isn't used on Windows, so avoid this useless work.
		            * XXX Probably the same for a lot of other places. */
		            {
         756                    Pid_t pid;
         756                    SV *sv;
		
		                LOCK_FDPID_MUTEX;
         756                    sv = *av_fetch(PL_fdpid,fd,TRUE);
         756                    SvUPGRADE(sv, SVt_IV);
         756                    pid = SvIVX(sv);
         756                    SvIV_set(sv, 0);
         756                    sv = *av_fetch(PL_fdpid,savefd,TRUE);
         756                    SvUPGRADE(sv, SVt_IV);
         756                    SvIV_set(sv, pid);
		                UNLOCK_FDPID_MUTEX;
		            }
		#endif
		
         756    	    if (was_fdopen) {
		                /* need to close fp without closing underlying fd */
          18                    int ofd = PerlIO_fileno(fp);
          18                    int dupfd = PerlLIO_dup(ofd);
		#if defined(HAS_FCNTL) && defined(F_SETFD)
				/* Assume if we have F_SETFD we have F_GETFD */
          18                    int coe = fcntl(ofd,F_GETFD);
		#endif
          18                    PerlIO_close(fp);
          18                    PerlLIO_dup2(dupfd,ofd);
		#if defined(HAS_FCNTL) && defined(F_SETFD)
				/* The dup trick has lost close-on-exec on ofd */
          18    		fcntl(ofd,F_SETFD, coe);
		#endif
          18                    PerlLIO_close(dupfd);
			    }
		            else
         738    		PerlIO_close(fp);
			}
         756    	fp = saveifp;
         756    	PerlIO_clearerr(fp);
         756    	fd = PerlIO_fileno(fp);
		    }
		#if defined(HAS_FCNTL) && defined(F_SETFD)
       21234        if (fd >= 0) {
       20298    	int save_errno = errno;
       20298    	fcntl(fd,F_SETFD,fd > PL_maxsysfd); /* can change errno */
       20298    	errno = save_errno;
		    }
		#endif
       21234        IoIFP(io) = fp;
		
       21234        IoFLAGS(io) &= ~IOf_NOLINE;
       21234        if (writing) {
       11934    	if (IoTYPE(io) == IoTYPE_SOCKET
			    || (IoTYPE(io) == IoTYPE_WRONLY && fd >= 0 && S_ISCHR(PL_statbuf.st_mode)) ) {
         486    	    char *s = mode;
         486    	    if (*s == IoTYPE_IMPLICIT || *s == IoTYPE_NUMERIC)
           1    	      s++;
         486    	    *s = 'w';
         486    	    if (!(IoOFP(io) = PerlIO_openn(aTHX_ type,s,fd,0,0,NULL,0,svp))) {
      ######    		PerlIO_close(fp);
      ######    		IoIFP(io) = Nullfp;
      ######    		goto say_false;
			    }
			}
			else
       11448    	    IoOFP(io) = fp;
		    }
       21234        return TRUE;
		
		say_false:
         736        IoIFP(io) = saveifp;
         736        IoOFP(io) = saveofp;
         736        IoTYPE(io) = savetype;
         736        return FALSE;
		}
		
		PerlIO *
		Perl_nextargv(pTHX_ register GV *gv)
          80    {
          80        register SV *sv;
		#ifndef FLEXFILENAMES
		    int filedev;
		    int fileino;
		#endif
          80        Uid_t fileuid;
          80        Gid_t filegid;
          80        IO *io = GvIOp(gv);
		
          80        if (!PL_argvoutgv)
          30    	PL_argvoutgv = gv_fetchpv("ARGVOUT",TRUE,SVt_PVIO);
          80        if (io && (IoFLAGS(io) & IOf_ARGV) && (IoFLAGS(io) & IOf_START)) {
          24    	IoFLAGS(io) &= ~IOf_START;
          24    	if (PL_inplace) {
           9    	    if (!PL_argvout_stack)
           6    		PL_argvout_stack = newAV();
           9    	    av_push(PL_argvout_stack, SvREFCNT_inc(PL_defoutgv));
			}
		    }
          80        if (PL_filemode & (S_ISUID|S_ISGID)) {
      ######    	PerlIO_flush(IoIFP(GvIOn(PL_argvoutgv)));  /* chmod must follow last write */
		#ifdef HAS_FCHMOD
      ######    	if (PL_lastfd != -1)
      ######    	    (void)fchmod(PL_lastfd,PL_filemode);
		#else
			(void)PerlLIO_chmod(PL_oldname,PL_filemode);
		#endif
		    }
          80        PL_lastfd = -1;
          80        PL_filemode = 0;
          80        if (!GvAV(gv))
      ######            return Nullfp;
          83        while (av_len(GvAV(gv)) >= 0) {
          44    	STRLEN oldlen;
          44    	sv = av_shift(GvAV(gv));
          44    	SAVEFREESV(sv);
          44    	sv_setsv(GvSVn(gv),sv);
          44    	SvSETMAGIC(GvSV(gv));
          44    	PL_oldname = SvPVx(GvSV(gv), oldlen);
          44    	if (do_open(gv,PL_oldname,oldlen,PL_inplace!=0,O_RDONLY,0,Nullfp)) {
          44    	    if (PL_inplace) {
          17    		TAINT_PROPER("inplace open");
          17    		if (oldlen == 1 && *PL_oldname == '-') {
      ######    		    setdefout(gv_fetchpv("STDOUT",TRUE,SVt_PVIO));
      ######    		    return IoIFP(GvIOp(gv));
				}
		#ifndef FLEXFILENAMES
				filedev = PL_statbuf.st_dev;
				fileino = PL_statbuf.st_ino;
		#endif
          17    		PL_filemode = PL_statbuf.st_mode;
          17    		fileuid = PL_statbuf.st_uid;
          17    		filegid = PL_statbuf.st_gid;
          17    		if (!S_ISREG(PL_filemode)) {
           3    		    if (ckWARN_d(WARN_INPLACE))	
           2    		        Perl_warner(aTHX_ packWARN(WARN_INPLACE),
					    "Can't do inplace edit: %s is not a regular file",
				            PL_oldname );
           3    		    do_close(gv,FALSE);
           3    		    continue;
				}
          14    		if (*PL_inplace) {
          14    		    char *star = strchr(PL_inplace, '*');
          14    		    if (star) {
           3    			char *begin = PL_inplace;
           3    			sv_setpvn(sv, "", 0);
           3    			do {
           3    			    sv_catpvn(sv, begin, star - begin);
           3    			    sv_catpvn(sv, PL_oldname, oldlen);
           3    			    begin = ++star;
           3    			} while ((star = strchr(begin, '*')));
           3    			if (*begin)
      ######    			    sv_catpv(sv,begin);
				    }
				    else {
          11    			sv_catpv(sv,PL_inplace);
				    }
		#ifndef FLEXFILENAMES
				    if ((PerlLIO_stat(SvPVX_const(sv),&PL_statbuf) >= 0
					 && PL_statbuf.st_dev == filedev
					 && PL_statbuf.st_ino == fileino)
		#ifdef DJGPP
					|| ((_djstat_fail_bits & _STFAIL_TRUENAME)!=0)
		#endif
		                      )
				    {
					if (ckWARN_d(WARN_INPLACE))	
					    Perl_warner(aTHX_ packWARN(WARN_INPLACE),
					      "Can't do inplace edit: %"SVf" would not be unique",
					      sv);
					do_close(gv,FALSE);
					continue;
				    }
		#endif
		#ifdef HAS_RENAME
		#if !defined(DOSISH) && !defined(__CYGWIN__) && !defined(EPOC)
          14    		    if (PerlLIO_rename(PL_oldname,SvPVX_const(sv)) < 0) {
      ######    		        if (ckWARN_d(WARN_INPLACE))	
      ######    			    Perl_warner(aTHX_ packWARN(WARN_INPLACE),
					      "Can't rename %s to %"SVf": %s, skipping file",
					      PL_oldname, sv, Strerror(errno) );
      ######    			do_close(gv,FALSE);
      ######    			continue;
				    }
		#else
				    do_close(gv,FALSE);
				    (void)PerlLIO_unlink(SvPVX_const(sv));
				    (void)PerlLIO_rename(PL_oldname,SvPVX_const(sv));
				    do_open(gv,(char*)SvPVX_const(sv),SvCUR(sv),PL_inplace!=0,
					    O_RDONLY,0,Nullfp);
		#endif /* DOSISH */
		#else
				    (void)UNLINK(SvPVX_const(sv));
				    if (link(PL_oldname,SvPVX_const(sv)) < 0) {
				        if (ckWARN_d(WARN_INPLACE))	
					    Perl_warner(aTHX_ packWARN(WARN_INPLACE),
					      "Can't rename %s to %"SVf": %s, skipping file",
					      PL_oldname, sv, Strerror(errno) );
					do_close(gv,FALSE);
					continue;
				    }
				    (void)UNLINK(PL_oldname);
		#endif
				}
				else {
		#if !defined(DOSISH) && !defined(AMIGAOS)
		#  ifndef VMS  /* Don't delete; use automatic file versioning */
      ######    		    if (UNLINK(PL_oldname) < 0) {
      ######    		        if (ckWARN_d(WARN_INPLACE))	
      ######    			    Perl_warner(aTHX_ packWARN(WARN_INPLACE),
					      "Can't remove %s: %s, skipping file",
					      PL_oldname, Strerror(errno) );
      ######    			do_close(gv,FALSE);
      ######    			continue;
				    }
		#  endif
		#else
				    Perl_croak(aTHX_ "Can't do inplace edit without backup");
		#endif
				}
		
          14    		sv_setpvn(sv,">",!PL_inplace);
          14    		sv_catpvn(sv,PL_oldname,oldlen);
          14    		SETERRNO(0,0);		/* in case sprintf set errno */
		#ifdef VMS
				if (!do_open(PL_argvoutgv,(char*)SvPVX_const(sv),SvCUR(sv),
					     PL_inplace!=0,O_WRONLY|O_CREAT|O_TRUNC,0,Nullfp))
		#else
          14    		    if (!do_open(PL_argvoutgv,(char*)SvPVX_const(sv),SvCUR(sv),
					     PL_inplace!=0,O_WRONLY|O_CREAT|OPEN_EXCL,0666,
					     Nullfp))
		#endif
				{
      ######    		    if (ckWARN_d(WARN_INPLACE))	
      ######    		        Perl_warner(aTHX_ packWARN(WARN_INPLACE), "Can't do inplace edit on %s: %s",
				          PL_oldname, Strerror(errno) );
      ######    		    do_close(gv,FALSE);
      ######    		    continue;
				}
          14    		setdefout(PL_argvoutgv);
          14    		PL_lastfd = PerlIO_fileno(IoIFP(GvIOp(PL_argvoutgv)));
          14    		(void)PerlLIO_fstat(PL_lastfd,&PL_statbuf);
		#ifdef HAS_FCHMOD
          14    		(void)fchmod(PL_lastfd,PL_filemode);
		#else
		#  if !(defined(WIN32) && defined(__BORLANDC__))
				/* Borland runtime creates a readonly file! */
				(void)PerlLIO_chmod(PL_oldname,PL_filemode);
		#  endif
		#endif
          14    		if (fileuid != PL_statbuf.st_uid || filegid != PL_statbuf.st_gid) {
		#ifdef HAS_FCHOWN
      ######    		    (void)fchown(PL_lastfd,fileuid,filegid);
		#else
		#ifdef HAS_CHOWN
				    (void)PerlLIO_chown(PL_oldname,fileuid,filegid);
		#endif
		#endif
				}
			    }
          41    	    return IoIFP(GvIOp(gv));
			}
			else {
      ######    	    if (ckWARN_d(WARN_INPLACE)) {
      ######    		const int eno = errno;
      ######    		if (PerlLIO_stat(PL_oldname, &PL_statbuf) >= 0
				    && !S_ISREG(PL_statbuf.st_mode))	
				{
      ######    		    Perl_warner(aTHX_ packWARN(WARN_INPLACE),
						"Can't do inplace edit: %s is not a regular file",
						PL_oldname);
				}
				else
      ######    		    Perl_warner(aTHX_ packWARN(WARN_INPLACE), "Can't open %s: %s",
						PL_oldname, Strerror(eno));
			    }
			}
		    }
          39        if (io && (IoFLAGS(io) & IOf_ARGV))
          39    	IoFLAGS(io) |= IOf_START;
          39        if (PL_inplace) {
           9    	(void)do_close(PL_argvoutgv,FALSE);
           9    	if (io && (IoFLAGS(io) & IOf_ARGV)
			    && PL_argvout_stack && AvFILLp(PL_argvout_stack) >= 0)
			{
           9    	    GV *oldout = (GV*)av_pop(PL_argvout_stack);
           9    	    setdefout(oldout);
           9    	    SvREFCNT_dec(oldout);
           9    	    return Nullfp;
			}
      ######    	setdefout(gv_fetchpv("STDOUT",TRUE,SVt_PVIO));
		    }
          30        return Nullfp;
		}
		
		#ifdef HAS_PIPE
		void
		Perl_do_pipe(pTHX_ SV *sv, GV *rgv, GV *wgv)
      ######    {
      ######        register IO *rstio;
      ######        register IO *wstio;
      ######        int fd[2];
		
      ######        if (!rgv)
      ######    	goto badexit;
      ######        if (!wgv)
      ######    	goto badexit;
		
      ######        rstio = GvIOn(rgv);
      ######        wstio = GvIOn(wgv);
		
      ######        if (IoIFP(rstio))
      ######    	do_close(rgv,FALSE);
      ######        if (IoIFP(wstio))
      ######    	do_close(wgv,FALSE);
		
      ######        if (PerlProc_pipe(fd) < 0)
      ######    	goto badexit;
      ######        IoIFP(rstio) = PerlIO_fdopen(fd[0], "r"PIPE_OPEN_MODE);
      ######        IoOFP(wstio) = PerlIO_fdopen(fd[1], "w"PIPE_OPEN_MODE);
      ######        IoOFP(rstio) = IoIFP(rstio);
      ######        IoIFP(wstio) = IoOFP(wstio);
      ######        IoTYPE(rstio) = IoTYPE_RDONLY;
      ######        IoTYPE(wstio) = IoTYPE_WRONLY;
      ######        if (!IoIFP(rstio) || !IoOFP(wstio)) {
      ######    	if (IoIFP(rstio)) PerlIO_close(IoIFP(rstio));
      ######    	else PerlLIO_close(fd[0]);
      ######    	if (IoOFP(wstio)) PerlIO_close(IoOFP(wstio));
      ######    	else PerlLIO_close(fd[1]);
      ######    	goto badexit;
		    }
		
      ######        sv_setsv(sv,&PL_sv_yes);
      ######        return;
		
		badexit:
      ######        sv_setsv(sv,&PL_sv_undef);
      ######        return;
		}
		#endif
		
		/* explicit renamed to avoid C++ conflict    -- kja */
		bool
		Perl_do_close(pTHX_ GV *gv, bool not_implicit)
       18237    {
       18237        bool retval;
       18237        IO *io;
		
       18237        if (!gv)
      ######    	gv = PL_argvgv;
       18237        if (!gv || SvTYPE(gv) != SVt_PVGV) {
           6    	if (not_implicit)
           6    	    SETERRNO(EBADF,SS_IVCHAN);
           6    	return FALSE;
		    }
       18231        io = GvIO(gv);
       18231        if (!io) {		/* never opened */
           4    	if (not_implicit) {
           4    	    if (ckWARN(WARN_UNOPENED)) /* no check for closed here */
           3    		report_evil_fh(gv, io, PL_op->op_type);
           3    	    SETERRNO(EBADF,SS_IVCHAN);
			}
           3    	return FALSE;
		    }
       18227        retval = io_close(io, not_implicit);
       18227        if (not_implicit) {
       18164    	IoLINES(io) = 0;
       18164    	IoPAGE(io) = 0;
       18164    	IoLINES_LEFT(io) = IoPAGE_LEN(io);
		    }
       18227        IoTYPE(io) = IoTYPE_CLOSED;
       18227        return retval;
		}
		
		bool
		Perl_io_close(pTHX_ IO *io, bool not_implicit)
       20728    {
       20728        bool retval = FALSE;
		
       20728        if (IoIFP(io)) {
       20696    	if (IoTYPE(io) == IoTYPE_PIPE) {
        1172    	    const int status = PerlProc_pclose(IoIFP(io));
        1172    	    if (not_implicit) {
        1163    		STATUS_NATIVE_SET(status);
        1163    		retval = (STATUS_UNIX == 0);
			    }
			    else {
           9    		retval = (status != -1);
			    }
			}
       19524    	else if (IoTYPE(io) == IoTYPE_STD)
          16    	    retval = TRUE;
			else {
       19508    	    if (IoOFP(io) && IoOFP(io) != IoIFP(io)) {		/* a socket */
         469    		bool prev_err = PerlIO_error(IoOFP(io));
         469    		retval = (PerlIO_close(IoOFP(io)) != EOF && !prev_err);
         469    		PerlIO_close(IoIFP(io));	/* clear stdio, fd already closed */
			    }
			    else {
       19039    		bool prev_err = PerlIO_error(IoIFP(io));
       19039    		retval = (PerlIO_close(IoIFP(io)) != EOF && !prev_err);
			    }
			}
       20696    	IoOFP(io) = IoIFP(io) = Nullfp;
		    }
          32        else if (not_implicit) {
          26    	SETERRNO(EBADF,SS_IVCHAN);
		    }
		
       20728        return retval;
		}
		
		bool
		Perl_do_eof(pTHX_ GV *gv)
        1548    {
        1548        register IO *io;
        1548        int ch;
		
        1548        io = GvIO(gv);
		
        1548        if (!io)
          18    	return TRUE;
        1530        else if (ckWARN(WARN_IO) && (IoTYPE(io) == IoTYPE_WRONLY))
           1    	report_evil_fh(gv, io, OP_phoney_OUTPUT_ONLY);
		
        1535        while (IoIFP(io)) {
        1525            int saverrno;
		
        1525            if (PerlIO_has_cntptr(IoIFP(io))) {	/* (the code works without this) */
        1524    	    if (PerlIO_get_cnt(IoIFP(io)) > 0)	/* cheat a little, since */
        1455    		return FALSE;			/* this is the most usual case */
		        }
		
          70    	saverrno = errno; /* getc and ungetc can stomp on errno */
          70    	ch = PerlIO_getc(IoIFP(io));
          70    	if (ch != EOF) {
          20    	    (void)PerlIO_ungetc(IoIFP(io),ch);
          20    	    errno = saverrno;
          20    	    return FALSE;
			}
          50    	errno = saverrno;
		
          50            if (PerlIO_has_cntptr(IoIFP(io)) && PerlIO_canset_cnt(IoIFP(io))) {
          49    	    if (PerlIO_get_cnt(IoIFP(io)) < -1)
      ######    		PerlIO_set_cnt(IoIFP(io),-1);
			}
          50    	if (PL_op->op_flags & OPf_SPECIAL) { /* not necessarily a real EOF yet? */
           9    	    if (gv != PL_argvgv || !nextargv(gv))	/* get another fp handy */
           4    		return TRUE;
			}
			else
          41    	    return TRUE;		/* normal fp, definitely end of file */
		    }
          10        return TRUE;
		}
		
		Off_t
		Perl_do_tell(pTHX_ GV *gv)
        5392    {
        5392        register IO *io = 0;
        5392        register PerlIO *fp;
		
        5392        if (gv && (io = GvIO(gv)) && (fp = IoIFP(io))) {
		#ifdef ULTRIX_STDIO_BOTCH
			if (PerlIO_eof(fp))
			    (void)PerlIO_seek(fp, 0L, 2);	/* ultrix 1.2 workaround */
		#endif
        5384    	return PerlIO_tell(fp);
		    }
           8        if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
           2    	report_evil_fh(gv, io, PL_op->op_type);
           8        SETERRNO(EBADF,RMS_IFI);
           8        return (Off_t)-1;
		}
		
		bool
		Perl_do_seek(pTHX_ GV *gv, Off_t pos, int whence)
       29041    {
       29041        register IO *io = 0;
       29041        register PerlIO *fp;
		
       29041        if (gv && (io = GvIO(gv)) && (fp = IoIFP(io))) {
		#ifdef ULTRIX_STDIO_BOTCH
			if (PerlIO_eof(fp))
			    (void)PerlIO_seek(fp, 0L, 2);	/* ultrix 1.2 workaround */
		#endif
       29036    	return PerlIO_seek(fp, pos, whence) >= 0;
		    }
           5        if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
           2    	report_evil_fh(gv, io, PL_op->op_type);
           5        SETERRNO(EBADF,RMS_IFI);
           5        return FALSE;
		}
		
		Off_t
		Perl_do_sysseek(pTHX_ GV *gv, Off_t pos, int whence)
          43    {
          43        register IO *io = 0;
          43        register PerlIO *fp;
		
          43        if (gv && (io = GvIO(gv)) && (fp = IoIFP(io)))
          38    	return PerlLIO_lseek(PerlIO_fileno(fp), pos, whence);
           5        if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
           2    	report_evil_fh(gv, io, PL_op->op_type);
           5        SETERRNO(EBADF,RMS_IFI);
           5        return (Off_t)-1;
		}
		
		int
		Perl_mode_from_discipline(pTHX_ SV *discp)
       11026    {
       11026        int mode = O_BINARY;
       11026        if (discp) {
         984    	STRLEN len;
         984    	const char *s = SvPV_const(discp,len);
        2026    	while (*s) {
        1042    	    if (*s == ':') {
         218    		switch (s[1]) {
				case 'r':
          40    		    if (s[2] == 'a' && s[3] == 'w'
					&& (!s[4] || s[4] == ':' || isSPACE(s[4])))
				    {
          40    			mode = O_BINARY;
          40    			s += 4;
          40    			len -= 4;
          40    			break;
				    }
				    /* FALL THROUGH */
				case 'c':
           9    		    if (s[2] == 'r' && s[3] == 'l' && s[4] == 'f'
					&& (!s[5] || s[5] == ':' || isSPACE(s[5])))
				    {
           9    			mode = O_TEXT;
           9    			s += 5;
           9    			len -= 5;
           9    			break;
				    }
				    /* FALL THROUGH */
				default:
         824    		    goto fail_discipline;
				}
			    }
         824    	    else if (isSPACE(*s)) {
          28    		++s;
          28    		--len;
			    }
			    else {
         965    		const char *end;
		fail_discipline:
         965    		end = strchr(s+1, ':');
         965    		if (!end)
         962    		    end = s+len;
		#ifndef PERLIO_LAYERS
				Perl_croak(aTHX_ "IO layers (like '%.*s') unavailable", end-s, s);
		#else
         965    		len -= end-s;
         965    		s = end;
		#endif
			    }
			}
		    }
       11026        return mode;
		}
		
		int
		Perl_do_binmode(pTHX_ PerlIO *fp, int iotype, int mode)
      ######    {
		 /* The old body of this is now in non-LAYER part of perlio.c
		  * This is a stub for any XS code which might have been calling it.
		  */
      ######     const char *name = ":raw";
		#ifdef PERLIO_USING_CRLF
		 if (!(mode & O_BINARY))
		     name = ":crlf";
		#endif
      ######     return PerlIO_binmode(aTHX_ fp, iotype, mode, name);
		}
		
		#if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE)
		I32
		my_chsize(int fd, Off_t length)
		{
		#ifdef F_FREESP
			/* code courtesy of William Kucharski */
		#define HAS_CHSIZE
		
		    struct flock fl;
		    Stat_t filebuf;
		
		    if (PerlLIO_fstat(fd, &filebuf) < 0)
			return -1;
		
		    if (filebuf.st_size < length) {
		
			/* extend file length */
		
			if ((PerlLIO_lseek(fd, (length - 1), 0)) < 0)
			    return -1;
		
			/* write a "0" byte */
		
			if ((PerlLIO_write(fd, "", 1)) != 1)
			    return -1;
		    }
		    else {
			/* truncate length */
		
			fl.l_whence = 0;
			fl.l_len = 0;
			fl.l_start = length;
			fl.l_type = F_WRLCK;    /* write lock on file space */
		
			/*
			* This relies on the UNDOCUMENTED F_FREESP argument to
			* fcntl(2), which truncates the file so that it ends at the
			* position indicated by fl.l_start.
			*
			* Will minor miracles never cease?
			*/
		
			if (fcntl(fd, F_FREESP, &fl) < 0)
			    return -1;
		
		    }
		    return 0;
		#else
		    Perl_croak_nocontext("truncate not implemented");
		#endif /* F_FREESP */
		    return -1;
		}
		#endif /* !HAS_TRUNCATE && !HAS_CHSIZE */
		
		bool
		Perl_do_print(pTHX_ register SV *sv, PerlIO *fp)
     1184661    {
     1184661        register const char *tmps;
     1184661        STRLEN len;
		
		    /* assuming fp is checked earlier */
     1184661        if (!sv)
      ######    	return TRUE;
     1184661        switch (SvTYPE(sv)) {
		    case SVt_NULL:
          32    	if (ckWARN(WARN_UNINITIALIZED))
          18    	    report_uninit(sv);
          31    	return TRUE;
		    case SVt_IV:
       20815    	if (SvIOK(sv)) {
       20815    	    if (SvGMAGICAL(sv))
      ######    		mg_get(sv);
       20815    	    if (SvIsUV(sv))
      ######    		PerlIO_printf(fp, "%"UVuf, (UV)SvUVX(sv));
			    else
       20815    		PerlIO_printf(fp, "%"IVdf, (IV)SvIVX(sv));
       20815    	    return !PerlIO_error(fp);
			}
			/* FALL THROUGH */
		    default:
     1163814    	if (PerlIO_isutf8(fp)) {
        2874    	    if (!SvUTF8(sv))
         865    		sv_utf8_upgrade_flags(sv = sv_mortalcopy(sv),
						      SV_GMAGIC|SV_UTF8_NO_ENCODING);
			}
     1160940    	else if (DO_UTF8(sv)) {
          57    	    if (!sv_utf8_downgrade((sv = sv_mortalcopy(sv)), TRUE)
				&& ckWARN_d(WARN_UTF8))
			    {
           7    		Perl_warner(aTHX_ packWARN(WARN_UTF8), "Wide character in print");
			    }
			}
     1163814    	tmps = SvPV_const(sv, len);
     1163813    	break;
		    }
		    /* To detect whether the process is about to overstep its
		     * filesize limit we would need getrlimit().  We could then
		     * also transparently raise the limit with setrlimit() --
		     * but only until the system hard limit/the filesystem limit,
		     * at which we would get EPERM.  Note that when using buffered
		     * io the write failure can be delayed until the flush/close. --jhi */
     1163813        if (len && (PerlIO_write(fp,tmps,len) == 0))
      ######    	return FALSE;
     1163813        return !PerlIO_error(fp);
		}
		
		I32
		Perl_my_stat(pTHX)
       57185    {
       57185        dSP;
       57185        IO *io;
       57185        GV* gv;
		
       57185        if (PL_op->op_flags & OPf_REF) {
        8731    	EXTEND(SP,1);
        8731    	gv = cGVOP_gv;
		      do_fstat:
        8914    	io = GvIO(gv);
        8914    	if (io && IoIFP(io)) {
         343    	    PL_statgv = gv;
         343    	    sv_setpvn(PL_statname,"", 0);
         343    	    PL_laststype = OP_STAT;
         343    	    return (PL_laststatval = PerlLIO_fstat(PerlIO_fileno(IoIFP(io)), &PL_statcache));
			}
			else {
        8571    	    if (gv == PL_defgv)
        8569    		return PL_laststatval;
           2    	    if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
           1    		report_evil_fh(gv, io, PL_op->op_type);
           2    	    PL_statgv = Nullgv;
           2    	    sv_setpvn(PL_statname,"", 0);
           2    	    return (PL_laststatval = -1);
			}
		    }
       48454        else if (PL_op->op_private & OPpFT_STACKED) {
           8    	return PL_laststatval;
		    }
		    else {
       48446    	SV* sv = POPs;
       48446    	const char *s;
       48446    	STRLEN len;
       48446    	PUTBACK;
       48446    	if (SvTYPE(sv) == SVt_PVGV) {
           2    	    gv = (GV*)sv;
           2    	    goto do_fstat;
			}
       48444    	else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV) {
         181    	    gv = (GV*)SvRV(sv);
         181    	    goto do_fstat;
			}
		
       48263    	s = SvPV_const(sv, len);
       48262    	PL_statgv = Nullgv;
       48262    	sv_setpvn(PL_statname, s, len);
       48262    	s = SvPVX_const(PL_statname);		/* s now NUL-terminated */
       48262    	PL_laststype = OP_STAT;
       48262    	PL_laststatval = PerlLIO_stat(s, &PL_statcache);
       48262    	if (PL_laststatval < 0 && ckWARN(WARN_NEWLINE) && strchr(s, '\n'))
      ######    	    Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "stat");
       48262    	return PL_laststatval;
		    }
		}
		
		static const char no_prev_lstat[] = "The stat preceding -l _ wasn't an lstat";
		
		I32
		Perl_my_lstat(pTHX)
         383    {
         383        dSP;
         383        SV *sv;
         383        if (PL_op->op_flags & OPf_REF) {
         151    	EXTEND(SP,1);
         151    	if (cGVOP_gv == PL_defgv) {
         149    	    if (PL_laststype != OP_LSTAT)
           2    		Perl_croak(aTHX_ no_prev_lstat);
         147    	    return PL_laststatval;
			}
           2    	if (ckWARN(WARN_IO)) {
           1    	    Perl_warner(aTHX_ packWARN(WARN_IO), "Use of -l on filehandle %s",
				    GvENAME(cGVOP_gv));
           1    	    return (PL_laststatval = -1);
			}
		    }
         232        else if (ckWARN(WARN_IO) && PL_laststype != OP_LSTAT
			    && (PL_op->op_private & OPpFT_STACKED))
      ######    	Perl_croak(aTHX_ no_prev_lstat);
		
         233        PL_laststype = OP_LSTAT;
         233        PL_statgv = Nullgv;
         233        sv = POPs;
         233        PUTBACK;
         233        if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV && ckWARN(WARN_IO)) {
           1    	Perl_warner(aTHX_ packWARN(WARN_IO), "Use of -l on filehandle %s",
				GvENAME((GV*) SvRV(sv)));
           1    	return (PL_laststatval = -1);
		    }
		    /* XXX Do really need to be calling SvPV() all these times? */
         232        sv_setpv(PL_statname,SvPV_nolen_const(sv));
         232        PL_laststatval = PerlLIO_lstat(SvPV_nolen_const(sv),&PL_statcache);
         232        if (PL_laststatval < 0 && ckWARN(WARN_NEWLINE) && strchr(SvPV_nolen_const(sv), '\n'))
      ######    	Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "lstat");
         232        return PL_laststatval;
		}
		
		#ifndef OS2
		bool
		Perl_do_aexec(pTHX_ SV *really, register SV **mark, register SV **sp)
          58    {
          58        return do_aexec5(really, mark, sp, 0, 0);
		}
		#endif
		
		bool
		Perl_do_aexec5(pTHX_ SV *really, register SV **mark, register SV **sp,
			       int fd, int do_report)
          86    {
		    dVAR;
		#if defined(MACOS_TRADITIONAL) || defined(SYMBIAN)
		    Perl_croak(aTHX_ "exec? I'm not *that* kind of operating system");
		#else
          86        register char **a;
          86        const char *tmps = Nullch;
		
          86        if (sp > mark) {
          86    	New(401,PL_Argv, sp - mark + 1, char*);
          86    	a = PL_Argv;
         449    	while (++mark <= sp) {
         363    	    if (*mark)
         363    		*a++ = (char*)SvPV_nolen_const(*mark);
			    else
      ######    		*a++ = "";
			}
          86    	*a = Nullch;
          86    	if (really)
           1    	    tmps = SvPV_nolen_const(really);
          86    	if ((!really && *PL_Argv[0] != '/') ||
			    (really && *tmps != '/'))		/* will execvp use PATH? */
          50    	    TAINT_ENV();		/* testing IFS here is overkill, probably */
          86    	PERL_FPU_PRE_EXEC
          86    	if (really && *tmps)
           1    	    PerlProc_execvp(tmps,EXEC_ARGV_CAST(PL_Argv));
			else
          85    	    PerlProc_execvp(PL_Argv[0],EXEC_ARGV_CAST(PL_Argv));
           5    	PERL_FPU_POST_EXEC
           5    	if (ckWARN(WARN_EXEC))
           2    	    Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't exec \"%s\": %s",
				(really ? tmps : PL_Argv[0]), Strerror(errno));
           5    	if (do_report) {
      ######    	    int e = errno;
		
      ######    	    PerlLIO_write(fd, (void*)&e, sizeof(int));
      ######    	    PerlLIO_close(fd);
			}
		    }
           5        do_execfree();
		#endif
           5        return FALSE;
		}
		
		void
		Perl_do_execfree(pTHX)
        4428    {
        4428        Safefree(PL_Argv);
        4428        PL_Argv = Null(char **);
        4428        Safefree(PL_Cmd);
        4428        PL_Cmd = Nullch;
		}
		
		#if !defined(OS2) && !defined(WIN32) && !defined(DJGPP) && !defined(EPOC) && !defined(SYMBIAN) && !defined(MACOS_TRADITIONAL)
		
		bool
		Perl_do_exec(pTHX_ char *cmd)
           6    {
           6        return do_exec3(cmd,0,0);
		}
		
		bool
		Perl_do_exec3(pTHX_ char *cmd, int fd, int do_report)
        4373    {
		    dVAR;
        4373        register char **a;
        4373        register char *s;
		
        4389        while (*cmd && isSPACE(*cmd))
          16    	cmd++;
		
		    /* save an extra exec if possible */
		
		#ifdef CSH
		    {
        4373            char flags[PERL_FLAGS_MAX];
        4373    	if (strnEQ(cmd,PL_cshname,PL_cshlen) &&
			    strnEQ(cmd+PL_cshlen," -c",3)) {
		#ifdef HAS_STRLCPY
		          strlcpy(flags, "-c", PERL_FLAGS_MAX);
		#else
           3    	  strcpy(flags,"-c");
		#endif
           3    	  s = cmd+PL_cshlen+3;
           3    	  if (*s == 'f') {
           3    	      s++;
		#ifdef HAS_STRLCPY
		              strlcat(flags, "f", PERL_FLAGS_MAX);
		#else
           3    	      strcat(flags,"f");
		#endif
			  }
           3    	  if (*s == ' ')
           3    	      s++;
           3    	  if (*s++ == '\'') {
           3    	      char *ncmd = s;
		
         118    	      while (*s)
         115    		  s++;
           3    	      if (s[-1] == '\n')
      ######    		  *--s = '\0';
           3    	      if (s[-1] == '\'') {
      ######    		  *--s = '\0';
      ######    		  PERL_FPU_PRE_EXEC
      ######    		  PerlProc_execl(PL_cshname,"csh", flags, ncmd, (char*)0);
      ######    		  PERL_FPU_POST_EXEC
      ######    		  *s = '\'';
      ######    		  return FALSE;
			      }
			  }
			}
		    }
		#endif /* CSH */
		
		    /* see if there are shell metacharacters in it */
		
        4373        if (*cmd == '.' && isSPACE(cmd[1]))
        4373    	goto doshell;
		
        4373        if (strnEQ(cmd,"exec",4) && isSPACE(cmd[4]))
        4373    	goto doshell;
		
        4373        for (s = cmd; *s && isALNUM(*s); s++) ;	/* catch VAR=val gizmo */
        4373        if (*s == '=')
      ######    	goto doshell;
		
      170012        for (s = cmd; *s; s++) {
      168294    	if (*s != ' ' && !isALPHA(*s) &&
			    strchr("$&*(){}[]'\";\\|?<>~`\n",*s)) {
        2655    	    if (*s == '\n' && !s[1]) {
      ######    		*s = '\0';
      ######    		break;
			    }
			    /* handle the 2>&1 construct at the end */
        2655    	    if (*s == '>' && s[1] == '&' && s[2] == '1'
				&& s > cmd + 1 && s[-1] == '2' && isSPACE(s[-2])
				&& (!s[3] || isSPACE(s[3])))
			    {
         187                    const char *t = s + 3;
		
         187    		while (*t && isSPACE(*t))
      ######    		    ++t;
         187    		if (!*t && (PerlLIO_dup2(1,2) != -1)) {
         187    		    s[-2] = '\0';
         187    		    break;
				}
			    }
			  doshell:
        2468    	    PERL_FPU_PRE_EXEC
        2468    	    PerlProc_execl(PL_sh_path, "sh", "-c", cmd, (char*)0);
      ######    	    PERL_FPU_POST_EXEC
      ######    	    return FALSE;
			}
		    }
		
        1905        New(402,PL_Argv, (s - cmd) / 2 + 2, char*);
        1905        PL_Cmd = savepvn(cmd, s-cmd);
        1905        a = PL_Argv;
        3451        for (s = PL_Cmd; *s;) {
        4620    	while (*s && isSPACE(*s)) s++;
        3451    	if (*s)
        3451    	    *(a++) = s;
       76777    	while (*s && !isSPACE(*s)) s++;
        3451    	if (*s)
        1546    	    *s++ = '\0';
		    }
        1905        *a = Nullch;
        1905        if (PL_Argv[0]) {
        1905    	PERL_FPU_PRE_EXEC
        1905    	PerlProc_execvp(PL_Argv[0],PL_Argv);
           1    	PERL_FPU_POST_EXEC
           1    	if (errno == ENOEXEC) {		/* for system V NIH syndrome */
      ######    	    do_execfree();
      ######    	    goto doshell;
			}
			{
           1    	    if (ckWARN(WARN_EXEC))
      ######    		Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't exec \"%s\": %s",
				    PL_Argv[0], Strerror(errno));
           1    	    if (do_report) {
      ######    		int e = errno;
      ######    		PerlLIO_write(fd, (void*)&e, sizeof(int));
      ######    		PerlLIO_close(fd);
			    }
			}
		    }
           1        do_execfree();
           1        return FALSE;
		}
		
		#endif /* OS2 || WIN32 */
		
		I32
		Perl_apply(pTHX_ I32 type, register SV **mark, register SV **sp)
        3382    {
        3382        register I32 val;
        3382        register I32 tot = 0;
        3382        const char *what;
        3382        const char *s;
        3382        SV **oldmark = mark;
		
		#define APPLY_TAINT_PROPER() \
		    STMT_START {							\
			if (PL_tainted) { TAINT_PROPER(what); }				\
		    } STMT_END
		
		    /* This is a first heuristic; it doesn't catch tainting magic. */
        3382        if (PL_tainting) {
         641    	while (++mark <= sp) {
         338    	    if (SvTAINTED(*mark)) {
          13    		TAINT;
				break;
			    }
			}
         316    	mark = oldmark;
		    }
        3382        switch (type) {
		    case OP_CHMOD:
         891    	what = "chmod";
         891    	APPLY_TAINT_PROPER();
         890    	if (++mark <= sp) {
         890    	    val = SvIVx(*mark);
         890    	    APPLY_TAINT_PROPER();
         890    	    tot = sp - mark;
        1781    	    while (++mark <= sp) {
         891    		const char *name = SvPV_nolen_const(*mark);
         891    		APPLY_TAINT_PROPER();
         891    		if (PerlLIO_chmod(name, val))
         159    		    tot--;
			    }
			}
           2    	break;
		#ifdef HAS_CHOWN
		    case OP_CHOWN:
           2    	what = "chown";
           2    	APPLY_TAINT_PROPER();
           1    	if (sp - mark > 2) {
      ######                register I32 val2;
      ######    	    val = SvIVx(*++mark);
      ######    	    val2 = SvIVx(*++mark);
      ######    	    APPLY_TAINT_PROPER();
      ######    	    tot = sp - mark;
      ######    	    while (++mark <= sp) {
      ######    		const char *name = SvPV_nolen_const(*mark);
      ######    		APPLY_TAINT_PROPER();
      ######    		if (PerlLIO_chown(name, val, val2))
      ######    		    tot--;
			    }
			}
         304    	break;
		#endif
		/*
		XXX Should we make lchown() directly available from perl?
		For now, we'll let Configure test for HAS_LCHOWN, but do
		nothing in the core.
		    --AD  5/1998
		*/
		#ifdef HAS_KILL
		    case OP_KILL:
         304    	what = "kill";
         304    	APPLY_TAINT_PROPER();
         119    	if (mark == sp)
      ######    	    break;
         119    	s = SvPVx_nolen_const(*++mark);
         119    	if (isALPHA(*s)) {
          14    	    if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
      ######    		s += 3;
          14    	    if ((val = whichsig(s)) < 0)
      ######    		Perl_croak(aTHX_ "Unrecognized signal name \"%s\"",s);
			}
			else
         105    	    val = SvIVx(*mark);
         119    	APPLY_TAINT_PROPER();
         119    	tot = sp - mark;
		#ifdef VMS
			/* kill() doesn't do process groups (job trees?) under VMS */
			if (val < 0) val = -val;
			if (val == SIGKILL) {
		#	    include <starlet.h>
			    /* Use native sys$delprc() to insure that target process is
			     * deleted; supervisor-mode images don't pay attention to
			     * CRTL's emulation of Unix-style signals and kill()
			     */
			    while (++mark <= sp) {
				I32 proc = SvIVx(*mark);
				register unsigned long int __vmssts;
				APPLY_TAINT_PROPER();
				if (!((__vmssts = sys$delprc(&proc,0)) & 1)) {
				    tot--;
				    switch (__vmssts) {
					case SS$_NONEXPR:
					case SS$_NOSUCHNODE:
					    SETERRNO(ESRCH,__vmssts);
					    break;
					case SS$_NOPRIV:
					    SETERRNO(EPERM,__vmssts);
					    break;
					default:
					    SETERRNO(EVMSERR,__vmssts);
				    }
				}
			    }
			    break;
			}
		#endif
         119    	if (val < 0) {
      ######    	    val = -val;
      ######    	    while (++mark <= sp) {
      ######    		I32 proc = SvIVx(*mark);
      ######    		APPLY_TAINT_PROPER();
		#ifdef HAS_KILLPG
      ######    		if (PerlProc_killpg(proc,val))	/* BSD */
		#else
				if (PerlProc_kill(-proc,val))	/* SYSV */
		#endif
      ######    		    tot--;
			    }
			}
			else {
         137    	    while (++mark <= sp) {
          18    		I32 proc = SvIVx(*mark);
          18    		APPLY_TAINT_PROPER();
          18    		if (PerlProc_kill(proc, val))
      ######    		    tot--;
			    }
			}
        1952    	break;
		#endif
		    case OP_UNLINK:
        1952    	what = "unlink";
        1952    	APPLY_TAINT_PROPER();
        1951    	tot = sp - mark;
        4385    	while (++mark <= sp) {
        2434    	    s = SvPV_nolen_const(*mark);
        2434    	    APPLY_TAINT_PROPER();
        2434    	    if (PL_euid || PL_unsafe) {
        2434    		if (UNLINK(s))
         987    		    tot--;
			    }
			    else {	/* don't let root wipe out directories without -U */
      ######    		if (PerlLIO_lstat(s,&PL_statbuf) < 0 || S_ISDIR(PL_statbuf.st_mode))
      ######    		    tot--;
				else {
      ######    		    if (UNLINK(s))
      ######    			tot--;
				}
			    }
			}
         233    	break;
		#ifdef HAS_UTIME
		    case OP_UTIME:
         233    	what = "utime";
         233    	APPLY_TAINT_PROPER();
         232    	if (sp - mark > 2) {
		#if defined(I_UTIME) || defined(VMS)
         230    	    struct utimbuf utbuf;
         230    	    struct utimbuf *utbufp = &utbuf;
		#else
			    struct {
				Time_t	actime;
				Time_t	modtime;
			    } utbuf;
			    void *utbufp = &utbuf;
		#endif
		
         230               SV* accessed = *++mark;
         230               SV* modified = *++mark;
		
		           /* Be like C, and if both times are undefined, let the C
		            * library figure out what to do.  This usually means
		            * "current time". */
		
         230               if ( accessed == &PL_sv_undef && modified == &PL_sv_undef )
      ######                    utbufp = NULL;
		           else {
         230                    Zero(&utbuf, sizeof utbuf, char);
		#ifdef BIG_TIME
		                utbuf.actime = (Time_t)SvNVx(accessed);  /* time accessed */
		                utbuf.modtime = (Time_t)SvNVx(modified); /* time modified */
		#else
         230                    utbuf.actime = (Time_t)SvIVx(accessed);  /* time accessed */
         230                    utbuf.modtime = (Time_t)SvIVx(modified); /* time modified */
		#endif
		            }
         230    	    APPLY_TAINT_PROPER();
         230    	    tot = sp - mark;
         460    	    while (++mark <= sp) {
         230    		char *name = SvPV_nolen(*mark);
         230    		APPLY_TAINT_PROPER();
         230    		if (PerlLIO_utime(name, utbufp))
           1    		    tot--;
			    }
			}
			else
           2    	    tot = 0;
			break;
		#endif
		    }
        3193        return tot;
		
		#undef APPLY_TAINT_PROPER
		}
		
		/* Do the permissions allow some operation?  Assumes statcache already set. */
		#ifndef VMS /* VMS' cando is in vms.c */
		bool
		Perl_cando(pTHX_ Mode_t mode, Uid_t effective, register const Stat_t *statbufp)
		/* Note: we use "effective" both for uids and gids.
		 * Here we are betting on Uid_t being equal or wider than Gid_t.  */
        2499    {
		#ifdef DOSISH
		    /* [Comments and code from Len Reed]
		     * MS-DOS "user" is similar to UNIX's "superuser," but can't write
		     * to write-protected files.  The execute permission bit is set
		     * by the Miscrosoft C library stat() function for the following:
		     *		.exe files
		     *		.com files
		     *		.bat files
		     *		directories
		     * All files and directories are readable.
		     * Directories and special files, e.g. "CON", cannot be
		     * write-protected.
		     * [Comment by Tom Dinger -- a directory can have the write-protect
		     *		bit set in the file system, but DOS permits changes to
		     *		the directory anyway.  In addition, all bets are off
		     *		here for networked software, such as Novell and
		     *		Sun's PC-NFS.]
		     */
		
		     /* Atari stat() does pretty much the same thing. we set x_bit_set_in_stat
		      * too so it will actually look into the files for magic numbers
		      */
		     return (mode & statbufp->st_mode) ? TRUE : FALSE;
		
		#else /* ! DOSISH */
        2499        if ((effective ? PL_euid : PL_uid) == 0) {	/* root is special */
      ######    	if (mode == S_IXUSR) {
      ######    	    if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
      ######    		return TRUE;
			}
			else
      ######    	    return TRUE;		/* root reads and writes anything */
      ######    	return FALSE;
		    }
        2499        if (statbufp->st_uid == (effective ? PL_euid : PL_uid) ) {
        1742    	if (statbufp->st_mode & mode)
        1730    	    return TRUE;	/* ok as "user" */
		    }
         757        else if (ingroup(statbufp->st_gid,effective)) {
      ######    	if (statbufp->st_mode & mode >> 3)
      ######    	    return TRUE;	/* ok as "group" */
		    }
         757        else if (statbufp->st_mode & mode >> 6)
         757    	return TRUE;	/* ok as "other" */
          12        return FALSE;
		#endif /* ! DOSISH */
		}
		#endif /* ! VMS */
		
		bool
		Perl_ingroup(pTHX_ Gid_t testgid, Uid_t effective)
         757    {
		#ifdef MACOS_TRADITIONAL
		    /* This is simply not correct for AppleShare, but fix it yerself. */
		    return TRUE;
		#else
         757        if (testgid == (effective ? PL_egid : PL_gid))
      ######    	return TRUE;
		#ifdef HAS_GETGROUPS
		#ifndef NGROUPS
		#define NGROUPS 32
		#endif
		    {
         757    	Groups_t gary[NGROUPS];
         757    	I32 anum;
		
         757    	anum = getgroups(NGROUPS,gary);
        2271    	while (--anum >= 0)
        1514    	    if (gary[anum] == testgid)
      ######    		return TRUE;
		    }
		#endif
         757        return FALSE;
		#endif
		}
		
		#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
		
		I32
		Perl_do_ipcget(pTHX_ I32 optype, SV **mark, SV **sp)
           6    {
           6        key_t key = (key_t)SvNVx(*++mark);
           6        const I32 n = (optype == OP_MSGGET) ? 0 : SvIVx(*++mark);
           6        const I32 flags = SvIVx(*++mark);
           6        (void)sp;
		
           6        SETERRNO(0,0);
           6        switch (optype)
		    {
		#ifdef HAS_MSG
		    case OP_MSGGET:
           3    	return msgget(key, flags);
		#endif
		#ifdef HAS_SEM
		    case OP_SEMGET:
           2    	return semget(key, n, flags);
		#endif
		#ifdef HAS_SHM
		    case OP_SHMGET:
           1    	return shmget(key, n, flags);
		#endif
		#if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
		    default:
			Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
		#endif
		    }
      ######        return -1;			/* should never happen */
		}
		
		I32
		Perl_do_ipcctl(pTHX_ I32 optype, SV **mark, SV **sp)
          22    {
          22        SV *astr;
          22        char *a;
          22        STRLEN infosize;
          22        I32 getinfo;
          22        I32 ret = -1;
          22        const I32 id  = SvIVx(*++mark);
          22        const I32 n   = (optype == OP_SEMCTL) ? SvIVx(*++mark) : 0;
          22        const I32 cmd = SvIVx(*++mark);
          22        (void)sp;
		
          22        astr = *++mark;
          22        infosize = 0;
          22        getinfo = (cmd == IPC_STAT);
		
          22        switch (optype)
		    {
		#ifdef HAS_MSG
		    case OP_MSGCTL:
           6    	if (cmd == IPC_STAT || cmd == IPC_SET)
           3    	    infosize = sizeof(struct msqid_ds);
           3    	break;
		#endif
		#ifdef HAS_SHM
		    case OP_SHMCTL:
           1    	if (cmd == IPC_STAT || cmd == IPC_SET)
      ######    	    infosize = sizeof(struct shmid_ds);
      ######    	break;
		#endif
		#ifdef HAS_SEM
		    case OP_SEMCTL:
		#ifdef Semctl
          15    	if (cmd == IPC_STAT || cmd == IPC_SET)
           2    	    infosize = sizeof(struct semid_ds);
          13    	else if (cmd == GETALL || cmd == SETALL)
			{
           8    	    struct semid_ds semds;
           8    	    union semun semun;
		#ifdef EXTRA_F_IN_SEMUN_BUF
		            semun.buff = &semds;
		#else
           8                semun.buf = &semds;
		#endif
           8    	    getinfo = (cmd == GETALL);
           8    	    if (Semctl(id, 0, IPC_STAT, semun) == -1)
      ######    		return -1;
           8    	    infosize = semds.sem_nsems * sizeof(short);
				/* "short" is technically wrong but much more portable
				   than guessing about u_?short(_t)? */
			}
		#else
			Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
		#endif
			break;
		#endif
		#if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
		    default:
			Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
		#endif
		    }
		
          22        if (infosize)
		    {
          13    	if (getinfo)
			{
           9    	    SvPV_force_nolen(astr);
           9    	    a = SvGROW(astr, infosize+1);
			}
			else
			{
           4    	    STRLEN len;
           4    	    a = SvPV(astr, len);
           4    	    if (len != infosize)
      ######    		Perl_croak(aTHX_ "Bad arg length for %s, is %lu, should be %ld",
				      PL_op_desc[optype],
				      (unsigned long)len,
				      (long)infosize);
			}
		    }
		    else
		    {
           9    	IV i = SvIV(astr);
           9    	a = INT2PTR(char *,i);		/* ouch */
		    }
          22        SETERRNO(0,0);
          22        switch (optype)
		    {
		#ifdef HAS_MSG
		    case OP_MSGCTL:
           6    	ret = msgctl(id, cmd, (struct msqid_ds *)a);
           6    	break;
		#endif
		#ifdef HAS_SEM
		    case OP_SEMCTL: {
		#ifdef Semctl
          15                union semun unsemds;
		
		#ifdef EXTRA_F_IN_SEMUN_BUF
		            unsemds.buff = (struct semid_ds *)a;
		#else
          15                unsemds.buf = (struct semid_ds *)a;
		#endif
          15    	    ret = Semctl(id, n, cmd, unsemds);
		#else
			    Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
		#endif
		        }
          15    	break;
		#endif
		#ifdef HAS_SHM
		    case OP_SHMCTL:
           1    	ret = shmctl(id, cmd, (struct shmid_ds *)a);
			break;
		#endif
		    }
          22        if (getinfo && ret >= 0) {
           9    	SvCUR_set(astr, infosize);
           9    	*SvEND(astr) = '\0';
           9    	SvSETMAGIC(astr);
		    }
          22        return ret;
		}
		
		I32
		Perl_do_msgsnd(pTHX_ SV **mark, SV **sp)
           3    {
		#ifdef HAS_MSG
           3        SV *mstr;
           3        const char *mbuf;
           3        I32 msize, flags;
           3        STRLEN len;
           3        const I32 id = SvIVx(*++mark);
           3        (void)sp;
		
           3        mstr = *++mark;
           3        flags = SvIVx(*++mark);
           3        mbuf = SvPV_const(mstr, len);
           3        if ((msize = len - sizeof(long)) < 0)
      ######    	Perl_croak(aTHX_ "Arg too short for msgsnd");
           3        SETERRNO(0,0);
           3        return msgsnd(id, (struct msgbuf *)mbuf, msize, flags);
		#else
		    Perl_croak(aTHX_ "msgsnd not implemented");
		#endif
		}
		
		I32
		Perl_do_msgrcv(pTHX_ SV **mark, SV **sp)
           3    {
		#ifdef HAS_MSG
           3        SV *mstr;
           3        char *mbuf;
           3        long mtype;
           3        I32 msize, flags, ret;
           3        const I32 id = SvIVx(*++mark);
           3        (void)sp;
		
           3        mstr = *++mark;
		    /* suppress warning when reading into undef var --jhi */
           3        if (! SvOK(mstr))
           2    	sv_setpvn(mstr, "", 0);
           3        msize = SvIVx(*++mark);
           3        mtype = (long)SvIVx(*++mark);
           3        flags = SvIVx(*++mark);
           3        SvPV_force_nolen(mstr);
           3        mbuf = SvGROW(mstr, sizeof(long)+msize+1);
		
           3        SETERRNO(0,0);
           3        ret = msgrcv(id, (struct msgbuf *)mbuf, msize, mtype, flags);
           3        if (ret >= 0) {
           3    	SvCUR_set(mstr, sizeof(long)+ret);
           3    	*SvEND(mstr) = '\0';
		#ifndef INCOMPLETE_TAINTS
			/* who knows who has been playing with this message? */
           3    	SvTAINTED_on(mstr);
		#endif
		    }
           3        return ret;
		#else
		    Perl_croak(aTHX_ "msgrcv not implemented");
		#endif
		}
		
		I32
		Perl_do_semop(pTHX_ SV **mark, SV **sp)
           1    {
		#ifdef HAS_SEM
           1        SV *opstr;
           1        const char *opbuf;
           1        STRLEN opsize;
           1        const I32 id = SvIVx(*++mark);
           1        (void)sp;
		
           1        opstr = *++mark;
           1        opbuf = SvPV_const(opstr, opsize);
           1        if (opsize < 3 * SHORTSIZE
			|| (opsize % (3 * SHORTSIZE))) {
      ######    	SETERRNO(EINVAL,LIB_INVARG);
      ######    	return -1;
		    }
           1        SETERRNO(0,0);
		    /* We can't assume that sizeof(struct sembuf) == 3 * sizeof(short). */
		    {
           1            const int nsops  = opsize / (3 * sizeof (short));
           1            int i      = nsops;
           1            short *ops = (short *) opbuf;
           1            short *o   = ops;
           1            struct sembuf *temps, *t;
           1            I32 result;
		
           1            New (0, temps, nsops, struct sembuf);
           1            t = temps;
           2            while (i--) {
           1                t->sem_num = *o++;
           1                t->sem_op  = *o++;
           1                t->sem_flg = *o++;
           1                t++;
		        }
           1            result = semop(id, temps, nsops);
           1            t = temps;
           1            o = ops;
           1            i = nsops;
           2            while (i--) {
           1                *o++ = t->sem_num;
           1                *o++ = t->sem_op;
           1                *o++ = t->sem_flg;
           1                t++;
		        }
           1            Safefree(temps);
           1            return result;
		    }
		#else
		    Perl_croak(aTHX_ "semop not implemented");
		#endif
		}
		
		I32
		Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp)
           2    {
		#ifdef HAS_SHM
           2        SV *mstr;
           2        char *shm;
           2        I32 mpos, msize;
           2        struct shmid_ds shmds;
           2        const I32 id = SvIVx(*++mark);
           2        (void)sp;
		
           2        mstr = *++mark;
           2        mpos = SvIVx(*++mark);
           2        msize = SvIVx(*++mark);
           2        SETERRNO(0,0);
           2        if (shmctl(id, IPC_STAT, &shmds) == -1)
      ######    	return -1;
           2        if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
      ######    	SETERRNO(EFAULT,SS_ACCVIO);		/* can't do as caller requested */
      ######    	return -1;
		    }
           2        shm = (char *)shmat(id, (char*)NULL, (optype == OP_SHMREAD) ? SHM_RDONLY : 0);
           2        if (shm == (char *)-1)	/* I hate System V IPC, I really do */
      ######    	return -1;
           2        if (optype == OP_SHMREAD) {
           1    	const char *mbuf;
			/* suppress warning when reading into undef var (tchrist 3/Mar/00) */
           1    	if (! SvOK(mstr))
           1    	    sv_setpvn(mstr, "", 0);
           1    	SvPV_force_nolen(mstr);
           1    	mbuf = SvGROW(mstr, msize+1);
		
           1    	Copy(shm + mpos, mbuf, msize, char);
           1    	SvCUR_set(mstr, msize);
           1    	*SvEND(mstr) = '\0';
           1    	SvSETMAGIC(mstr);
		#ifndef INCOMPLETE_TAINTS
			/* who knows who has been playing with this shared memory? */
           1    	SvTAINTED_on(mstr);
		#endif
		    }
		    else {
           1    	I32 n;
           1    	STRLEN len;
		
           1    	const char *mbuf = SvPV_const(mstr, len);
           1    	if ((n = len) > msize)
      ######    	    n = msize;
           1    	Copy(mbuf, shm + mpos, n, char);
           1    	if (n < msize)
           1    	    memzero(shm + mpos + n, msize - n);
		    }
           2        return shmdt(shm);
		#else
		    Perl_croak(aTHX_ "shm I/O not implemented");
		#endif
		}
		
		#endif /* SYSV IPC */
		
		/*
		=head1 IO Functions
		
		=for apidoc start_glob
		
		Function called by C<do_readline> to spawn a glob (or do the glob inside
		perl on VMS). This code used to be inline, but now perl uses C<File::Glob>
		this glob starter is only used by miniperl during the build process.
		Moving it away shrinks pp_hot.c; shrinking pp_hot.c helps speed perl up.
		
		=cut
		*/
		
		PerlIO *
		Perl_start_glob (pTHX_ SV *tmpglob, IO *io)
           3    {
		    dVAR;
           3        SV *tmpcmd = NEWSV(55, 0);
           3        PerlIO *fp;
           3        ENTER;
           3        SAVEFREESV(tmpcmd);
		#ifdef VMS /* expand the wildcards right here, rather than opening a pipe, */
		           /* since spawning off a process is a real performance hit */
		    {
		#include <descrip.h>
		#include <lib$routines.h>
		#include <nam.h>
		#include <rmsdef.h>
			char rslt[NAM$C_MAXRSS+1+sizeof(unsigned short int)] = {'\0','\0'};
			char vmsspec[NAM$C_MAXRSS+1];
			char *rstr = rslt + sizeof(unsigned short int), *begin, *end, *cp;
			$DESCRIPTOR(dfltdsc,"SYS$DISK:[]*.*;");
			PerlIO *tmpfp;
			STRLEN i;
			struct dsc$descriptor_s wilddsc
			    = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
			struct dsc$descriptor_vs rsdsc
			    = {sizeof rslt, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, rslt};
			unsigned long int cxt = 0, sts = 0, ok = 1, hasdir = 0, hasver = 0, isunix = 0;
		
			/* We could find out if there's an explicit dev/dir or version
			   by peeking into lib$find_file's internal context at
			   ((struct NAM *)((struct FAB *)cxt)->fab$l_nam)->nam$l_fnb
			   but that's unsupported, so I don't want to do it now and
			   have it bite someone in the future. */
			cp = SvPV(tmpglob,i);
			for (; i; i--) {
			    if (cp[i] == ';') hasver = 1;
			    if (cp[i] == '.') {
				if (sts) hasver = 1;
				else sts = 1;
			    }
			    if (cp[i] == '/') {
				hasdir = isunix = 1;
				break;
			    }
			    if (cp[i] == ']' || cp[i] == '>' || cp[i] == ':') {
				hasdir = 1;
				break;
			    }
			}
		       if ((tmpfp = PerlIO_tmpfile()) != NULL) {
			    Stat_t st;
			    if (!PerlLIO_stat(SvPVX_const(tmpglob),&st) && S_ISDIR(st.st_mode))
				ok = ((wilddsc.dsc$a_pointer = tovmspath(SvPVX(tmpglob),vmsspec)) != NULL);
			    else ok = ((wilddsc.dsc$a_pointer = tovmsspec(SvPVX(tmpglob),vmsspec)) != NULL);
			    if (ok) wilddsc.dsc$w_length = (unsigned short int) strlen(wilddsc.dsc$a_pointer);
			    for (cp=wilddsc.dsc$a_pointer; ok && cp && *cp; cp++)
				if (*cp == '?') *cp = '%';  /* VMS style single-char wildcard */
			    while (ok && ((sts = lib$find_file(&wilddsc,&rsdsc,&cxt,
							       &dfltdsc,NULL,NULL,NULL))&1)) {
				/* with varying string, 1st word of buffer contains result length */
				end = rstr + *((unsigned short int*)rslt);
				if (!hasver) while (*end != ';' && end > rstr) end--;
				*(end++) = '\n';  *end = '\0';
				for (cp = rstr; *cp; cp++) *cp = _tolower(*cp);
				if (hasdir) {
				    if (isunix) trim_unixpath(rstr,SvPVX(tmpglob),1);
				    begin = rstr;
				}
				else {
				    begin = end;
				    while (*(--begin) != ']' && *begin != '>') ;
				    ++begin;
				}
				ok = (PerlIO_puts(tmpfp,begin) != EOF);
			    }
			    if (cxt) (void)lib$find_file_end(&cxt);
			    if (ok && sts != RMS$_NMF &&
				sts != RMS$_DNF && sts != RMS_FNF) ok = 0;
			    if (!ok) {
				if (!(sts & 1)) {
				    SETERRNO((sts == RMS$_SYN ? EINVAL : EVMSERR),sts);
				}
				PerlIO_close(tmpfp);
				fp = NULL;
			    }
			    else {
				PerlIO_rewind(tmpfp);
				IoTYPE(io) = IoTYPE_RDONLY;
				IoIFP(io) = fp = tmpfp;
				IoFLAGS(io) &= ~IOf_UNTAINT;  /* maybe redundant */
			    }
			}
		    }
		#else /* !VMS */
		#ifdef MACOS_TRADITIONAL
		    sv_setpv(tmpcmd, "glob ");
		    sv_catsv(tmpcmd, tmpglob);
		    sv_catpv(tmpcmd, " |");
		#else
		#ifdef DOSISH
		#ifdef OS2
		    sv_setpv(tmpcmd, "for a in ");
		    sv_catsv(tmpcmd, tmpglob);
		    sv_catpv(tmpcmd, "; do echo \"$a\\0\\c\"; done |");
		#else
		#ifdef DJGPP
		    sv_setpv(tmpcmd, "/dev/dosglob/"); /* File System Extension */
		    sv_catsv(tmpcmd, tmpglob);
		#else
		    sv_setpv(tmpcmd, "perlglob ");
		    sv_catsv(tmpcmd, tmpglob);
		    sv_catpv(tmpcmd, " |");
		#endif /* !DJGPP */
		#endif /* !OS2 */
		#else /* !DOSISH */
		#if defined(CSH)
           3        sv_setpvn(tmpcmd, PL_cshname, PL_cshlen);
           3        sv_catpv(tmpcmd, " -cf 'set nonomatch; glob ");
           3        sv_catsv(tmpcmd, tmpglob);
           3        sv_catpv(tmpcmd, "' 2>/dev/null |");
		#else
		    sv_setpv(tmpcmd, "echo ");
		    sv_catsv(tmpcmd, tmpglob);
		#if 'z' - 'a' == 25
		    sv_catpv(tmpcmd, "|tr -s ' \t\f\r' '\\012\\012\\012\\012'|");
		#else
		    sv_catpv(tmpcmd, "|tr -s ' \t\f\r' '\\n\\n\\n\\n'|");
		#endif
		#endif /* !CSH */
		#endif /* !DOSISH */
		#endif /* MACOS_TRADITIONAL */
           3        (void)do_open(PL_last_in_gv, (char*)SvPVX_const(tmpcmd), SvCUR(tmpcmd),
				  FALSE, O_RDONLY, 0, Nullfp);
           3        fp = IoIFP(io);
		#endif /* !VMS */
           3        LEAVE;
           3        return fp;
		}
		
		/*
		 * Local variables:
		 * c-indentation-style: bsd
		 * c-basic-offset: 4
		 * indent-tabs-mode: t
		 * End:
		 *
		 * ex: set ts=8 sts=4 sw=4 noet:
		 */
