S_pmtrans(): always use op_private flag variables
[perl.git] / doio.c
1 /*    doio.c
2  *
3  *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
4  *    2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others
5  *
6  *    You may distribute under the terms of either the GNU General Public
7  *    License or the Artistic License, as specified in the README file.
8  *
9  */
10
11 /*
12  *  Far below them they saw the white waters pour into a foaming bowl, and
13  *  then swirl darkly about a deep oval basin in the rocks, until they found
14  *  their way out again through a narrow gate, and flowed away, fuming and
15  *  chattering, into calmer and more level reaches.
16  *
17  *     [p.684 of _The Lord of the Rings_, IV/vi: "The Forbidden Pool"]
18  */
19
20 /* This file contains functions that do the actual I/O on behalf of ops.
21  * For example, pp_print() calls the do_print() function in this file for
22  * each argument needing printing.
23  */
24
25 #include "EXTERN.h"
26 #define PERL_IN_DOIO_C
27 #include "perl.h"
28
29 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
30 #ifndef HAS_SEM
31 #include <sys/ipc.h>
32 #endif
33 #ifdef HAS_MSG
34 #include <sys/msg.h>
35 #endif
36 #ifdef HAS_SHM
37 #include <sys/shm.h>
38 # ifndef HAS_SHMAT_PROTOTYPE
39     extern Shmat_t shmat (int, char *, int);
40 # endif
41 #endif
42 #endif
43
44 #ifdef I_UTIME
45 #  if defined(_MSC_VER) || defined(__MINGW32__)
46 #    include <sys/utime.h>
47 #  else
48 #    include <utime.h>
49 #  endif
50 #endif
51
52 #ifdef O_EXCL
53 #  define OPEN_EXCL O_EXCL
54 #else
55 #  define OPEN_EXCL 0
56 #endif
57
58 #define PERL_MODE_MAX 8
59 #define PERL_FLAGS_MAX 10
60
61 #include <signal.h>
62
63 void
64 Perl_setfd_cloexec(int fd)
65 {
66     assert(fd >= 0);
67 #if defined(HAS_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC)
68     (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
69 #endif
70 }
71
72 void
73 Perl_setfd_inhexec(int fd)
74 {
75     assert(fd >= 0);
76 #if defined(HAS_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC)
77     (void) fcntl(fd, F_SETFD, 0);
78 #endif
79 }
80
81 void
82 Perl_setfd_cloexec_for_nonsysfd(pTHX_ int fd)
83 {
84     assert(fd >= 0);
85     if(fd > PL_maxsysfd)
86         setfd_cloexec(fd);
87 }
88
89 void
90 Perl_setfd_inhexec_for_sysfd(pTHX_ int fd)
91 {
92     assert(fd >= 0);
93     if(fd <= PL_maxsysfd)
94         setfd_inhexec(fd);
95 }
96 void
97 Perl_setfd_cloexec_or_inhexec_by_sysfdness(pTHX_ int fd)
98 {
99     assert(fd >= 0);
100     if(fd <= PL_maxsysfd)
101         setfd_inhexec(fd);
102     else
103         setfd_cloexec(fd);
104 }
105
106
107 #define DO_GENOPEN_THEN_CLOEXEC(GENOPEN_NORMAL, GENSETFD_CLOEXEC) \
108         do { \
109             int res = (GENOPEN_NORMAL); \
110             if(LIKELY(res != -1)) GENSETFD_CLOEXEC; \
111             return res; \
112         } while(0)
113 #if defined(HAS_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC) && \
114                         defined(F_GETFD)
115 enum { CLOEXEC_EXPERIMENT, CLOEXEC_AT_OPEN, CLOEXEC_AFTER_OPEN };
116 #  define DO_GENOPEN_EXPERIMENTING_CLOEXEC(TESTFD, GENOPEN_CLOEXEC, \
117                         GENOPEN_NORMAL, GENSETFD_CLOEXEC) \
118         do { \
119             static int strategy = CLOEXEC_EXPERIMENT; \
120             switch (strategy) { \
121                 case CLOEXEC_EXPERIMENT: default: { \
122                     int res = (GENOPEN_CLOEXEC), eno; \
123                     if (LIKELY(res != -1)) { \
124                         int fdflags = fcntl((TESTFD), F_GETFD); \
125                         if (LIKELY(fdflags != -1) && \
126                                 LIKELY(fdflags & FD_CLOEXEC)) { \
127                             strategy = CLOEXEC_AT_OPEN; \
128                         } else { \
129                             strategy = CLOEXEC_AFTER_OPEN; \
130                             GENSETFD_CLOEXEC; \
131                         } \
132                     } else if (UNLIKELY((eno = errno) == EINVAL || \
133                                                 eno == ENOSYS)) { \
134                         res = (GENOPEN_NORMAL); \
135                         if (LIKELY(res != -1)) { \
136                             strategy = CLOEXEC_AFTER_OPEN; \
137                             GENSETFD_CLOEXEC; \
138                         } else if (!LIKELY((eno = errno) == EINVAL || \
139                                                 eno == ENOSYS)) { \
140                             strategy = CLOEXEC_AFTER_OPEN; \
141                         } \
142                     } \
143                     return res; \
144                 } \
145                 case CLOEXEC_AT_OPEN: \
146                     return (GENOPEN_CLOEXEC); \
147                 case CLOEXEC_AFTER_OPEN: \
148                     DO_GENOPEN_THEN_CLOEXEC(GENOPEN_NORMAL, GENSETFD_CLOEXEC); \
149             } \
150         } while(0)
151 #else
152 #  define DO_GENOPEN_EXPERIMENTING_CLOEXEC(TESTFD, GENOPEN_CLOEXEC, \
153                         GENOPEN_NORMAL, GENSETFD_CLOEXEC) \
154         DO_GENOPEN_THEN_CLOEXEC(GENOPEN_NORMAL, GENSETFD_CLOEXEC)
155 #endif
156
157 #define DO_ONEOPEN_THEN_CLOEXEC(ONEOPEN_NORMAL) \
158         do { \
159             int fd; \
160             DO_GENOPEN_THEN_CLOEXEC(fd = (ONEOPEN_NORMAL), \
161                 setfd_cloexec(fd)); \
162         } while(0)
163 #define DO_ONEOPEN_EXPERIMENTING_CLOEXEC(ONEOPEN_CLOEXEC, ONEOPEN_NORMAL) \
164         do { \
165             int fd; \
166             DO_GENOPEN_EXPERIMENTING_CLOEXEC(fd, fd = (ONEOPEN_CLOEXEC), \
167                 fd = (ONEOPEN_NORMAL), setfd_cloexec(fd)); \
168         } while(0)
169
170 #define DO_PIPESETFD_CLOEXEC(PIPEFD) \
171         do { \
172             setfd_cloexec((PIPEFD)[0]); \
173             setfd_cloexec((PIPEFD)[1]); \
174         } while(0)
175 #define DO_PIPEOPEN_THEN_CLOEXEC(PIPEFD, PIPEOPEN_NORMAL) \
176         DO_GENOPEN_THEN_CLOEXEC(PIPEOPEN_NORMAL, DO_PIPESETFD_CLOEXEC(PIPEFD))
177 #define DO_PIPEOPEN_EXPERIMENTING_CLOEXEC(PIPEFD, PIPEOPEN_CLOEXEC, \
178                         PIPEOPEN_NORMAL) \
179         DO_GENOPEN_EXPERIMENTING_CLOEXEC((PIPEFD)[0], PIPEOPEN_CLOEXEC, \
180             PIPEOPEN_NORMAL, DO_PIPESETFD_CLOEXEC(PIPEFD))
181
182 int
183 Perl_PerlLIO_dup_cloexec(pTHX_ int oldfd)
184 {
185 #if !defined(PERL_IMPLICIT_SYS) && defined(F_DUPFD_CLOEXEC)
186     /*
187      * struct IPerlLIO doesn't cover fcntl(), and there's no clear way
188      * to extend it, so for the time being this just isn't available on
189      * PERL_IMPLICIT_SYS builds.
190      */
191     DO_ONEOPEN_EXPERIMENTING_CLOEXEC(
192         fcntl(oldfd, F_DUPFD_CLOEXEC, 0),
193         PerlLIO_dup(oldfd));
194 #else
195     DO_ONEOPEN_THEN_CLOEXEC(PerlLIO_dup(oldfd));
196 #endif
197 }
198
199 int
200 Perl_PerlLIO_dup2_cloexec(pTHX_ int oldfd, int newfd)
201 {
202 #if !defined(PERL_IMPLICIT_SYS) && defined(HAS_DUP3) && defined(O_CLOEXEC)
203     /*
204      * struct IPerlLIO doesn't cover dup3(), and there's no clear way
205      * to extend it, so for the time being this just isn't available on
206      * PERL_IMPLICIT_SYS builds.
207      */
208     DO_ONEOPEN_EXPERIMENTING_CLOEXEC(
209         dup3(oldfd, newfd, O_CLOEXEC),
210         PerlLIO_dup2(oldfd, newfd));
211 #else
212     DO_ONEOPEN_THEN_CLOEXEC(PerlLIO_dup2(oldfd, newfd));
213 #endif
214 }
215
216 int
217 Perl_PerlLIO_open_cloexec(pTHX_ const char *file, int flag)
218 {
219     PERL_ARGS_ASSERT_PERLLIO_OPEN_CLOEXEC;
220 #if defined(O_CLOEXEC)
221     DO_ONEOPEN_EXPERIMENTING_CLOEXEC(
222         PerlLIO_open(file, flag | O_CLOEXEC),
223         PerlLIO_open(file, flag));
224 #else
225     DO_ONEOPEN_THEN_CLOEXEC(PerlLIO_open(file, flag));
226 #endif
227 }
228
229 int
230 Perl_PerlLIO_open3_cloexec(pTHX_ const char *file, int flag, int perm)
231 {
232     PERL_ARGS_ASSERT_PERLLIO_OPEN3_CLOEXEC;
233 #if defined(O_CLOEXEC)
234     DO_ONEOPEN_EXPERIMENTING_CLOEXEC(
235         PerlLIO_open3(file, flag | O_CLOEXEC, perm),
236         PerlLIO_open3(file, flag, perm));
237 #else
238     DO_ONEOPEN_THEN_CLOEXEC(PerlLIO_open3(file, flag, perm));
239 #endif
240 }
241
242 int
243 Perl_my_mkstemp_cloexec(char *templte)
244 {
245     PERL_ARGS_ASSERT_MY_MKSTEMP_CLOEXEC;
246 #if defined(O_CLOEXEC)
247     DO_ONEOPEN_EXPERIMENTING_CLOEXEC(
248         Perl_my_mkostemp(templte, O_CLOEXEC),
249         Perl_my_mkstemp(templte));
250 #else
251     DO_ONEOPEN_THEN_CLOEXEC(Perl_my_mkstemp(templte));
252 #endif
253 }
254
255 #ifdef HAS_PIPE
256 int
257 Perl_PerlProc_pipe_cloexec(pTHX_ int *pipefd)
258 {
259     PERL_ARGS_ASSERT_PERLPROC_PIPE_CLOEXEC;
260     /*
261      * struct IPerlProc doesn't cover pipe2(), and there's no clear way
262      * to extend it, so for the time being this just isn't available on
263      * PERL_IMPLICIT_SYS builds.
264      */
265 #  if !defined(PERL_IMPLICIT_SYS) && defined(HAS_PIPE2) && defined(O_CLOEXEC)
266     DO_PIPEOPEN_EXPERIMENTING_CLOEXEC(pipefd,
267         pipe2(pipefd, O_CLOEXEC),
268         PerlProc_pipe(pipefd));
269 #  else
270     DO_PIPEOPEN_THEN_CLOEXEC(pipefd, PerlProc_pipe(pipefd));
271 #  endif
272 }
273 #endif
274
275 #ifdef HAS_SOCKET
276
277 int
278 Perl_PerlSock_socket_cloexec(pTHX_ int domain, int type, int protocol)
279 {
280 #  if defined(SOCK_CLOEXEC)
281     DO_ONEOPEN_EXPERIMENTING_CLOEXEC(
282         PerlSock_socket(domain, type | SOCK_CLOEXEC, protocol),
283         PerlSock_socket(domain, type, protocol));
284 #  else
285     DO_ONEOPEN_THEN_CLOEXEC(PerlSock_socket(domain, type, protocol));
286 #  endif
287 }
288
289 int
290 Perl_PerlSock_accept_cloexec(pTHX_ int listenfd, struct sockaddr *addr,
291     Sock_size_t *addrlen)
292 {
293 #  if !defined(PERL_IMPLICIT_SYS) && \
294         defined(HAS_ACCEPT4) && defined(SOCK_CLOEXEC)
295     /*
296      * struct IPerlSock doesn't cover accept4(), and there's no clear
297      * way to extend it, so for the time being this just isn't available
298      * on PERL_IMPLICIT_SYS builds.
299      */
300     DO_ONEOPEN_EXPERIMENTING_CLOEXEC(
301         accept4(listenfd, addr, addrlen, SOCK_CLOEXEC),
302         PerlSock_accept(listenfd, addr, addrlen));
303 #  else
304     DO_ONEOPEN_THEN_CLOEXEC(PerlSock_accept(listenfd, addr, addrlen));
305 #  endif
306 }
307
308 #endif
309
310 #if defined (HAS_SOCKETPAIR) || \
311     (defined (HAS_SOCKET) && defined(SOCK_DGRAM) && \
312         defined(AF_INET) && defined(PF_INET))
313 int
314 Perl_PerlSock_socketpair_cloexec(pTHX_ int domain, int type, int protocol,
315     int *pairfd)
316 {
317     PERL_ARGS_ASSERT_PERLSOCK_SOCKETPAIR_CLOEXEC;
318 #  ifdef SOCK_CLOEXEC
319     DO_PIPEOPEN_EXPERIMENTING_CLOEXEC(pairfd,
320         PerlSock_socketpair(domain, type | SOCK_CLOEXEC, protocol, pairfd),
321         PerlSock_socketpair(domain, type, protocol, pairfd));
322 #  else
323     DO_PIPEOPEN_THEN_CLOEXEC(pairfd,
324         PerlSock_socketpair(domain, type, protocol, pairfd));
325 #  endif
326 }
327 #endif
328
329 static IO *
330 S_openn_setup(pTHX_ GV *gv, char *mode, PerlIO **saveifp, PerlIO **saveofp,
331               int *savefd,  char *savetype)
332 {
333     IO * const io = GvIOn(gv);
334
335     PERL_ARGS_ASSERT_OPENN_SETUP;
336
337     *saveifp = NULL;
338     *saveofp = NULL;
339     *savefd = -1;
340     *savetype = IoTYPE_CLOSED;
341
342     Zero(mode,sizeof(mode),char);
343     PL_forkprocess = 1;         /* assume true if no fork */
344
345     /* If currently open - close before we re-open */
346     if (IoIFP(io)) {
347         if (IoTYPE(io) == IoTYPE_STD) {
348             /* This is a clone of one of STD* handles */
349         }
350         else {
351             const int old_fd = PerlIO_fileno(IoIFP(io));
352
353             if (old_fd >= 0 && old_fd <= PL_maxsysfd) {
354                 /* This is one of the original STD* handles */
355                 *saveifp  = IoIFP(io);
356                 *saveofp  = IoOFP(io);
357                 *savetype = IoTYPE(io);
358                 *savefd   = old_fd;
359             }
360             else {
361                 int result;
362
363                 if (IoTYPE(io) == IoTYPE_PIPE)
364                     result = PerlProc_pclose(IoIFP(io));
365                 else if (IoIFP(io) != IoOFP(io)) {
366                     if (IoOFP(io)) {
367                         result = PerlIO_close(IoOFP(io));
368                         PerlIO_close(IoIFP(io)); /* clear stdio, fd already closed */
369                     }
370                     else
371                         result = PerlIO_close(IoIFP(io));
372                 }
373                 else
374                     result = PerlIO_close(IoIFP(io));
375
376                 if (result == EOF && old_fd > PL_maxsysfd) {
377                     /* Why is this not Perl_warn*() call ? */
378                     PerlIO_printf(Perl_error_log,
379                                   "Warning: unable to close filehandle %" HEKf
380                                   " properly.\n",
381                                   HEKfARG(GvENAME_HEK(gv))
382                         );
383                 }
384             }
385         }
386         IoOFP(io) = IoIFP(io) = NULL;
387     }
388     return io;
389 }
390
391 bool
392 Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw,
393               int rawmode, int rawperm, PerlIO *supplied_fp, SV **svp,
394               I32 num_svs)
395 {
396     PERL_ARGS_ASSERT_DO_OPENN;
397
398     if (as_raw) {
399         /* sysopen style args, i.e. integer mode and permissions */
400
401         if (num_svs != 0) {
402             Perl_croak(aTHX_ "panic: sysopen with multiple args, num_svs=%ld",
403                        (long) num_svs);
404         }
405         return do_open_raw(gv, oname, len, rawmode, rawperm, NULL);
406     }
407     return do_open6(gv, oname, len, supplied_fp, svp, num_svs);
408 }
409
410 bool
411 Perl_do_open_raw(pTHX_ GV *gv, const char *oname, STRLEN len,
412                  int rawmode, int rawperm, Stat_t *statbufp)
413 {
414     PerlIO *saveifp;
415     PerlIO *saveofp;
416     int savefd;
417     char savetype;
418     char mode[PERL_MODE_MAX];   /* file mode ("r\0", "rb\0", "ab\0" etc.) */
419     IO * const io = openn_setup(gv, mode, &saveifp, &saveofp, &savefd, &savetype);
420     int writing = 0;
421     PerlIO *fp;
422
423     PERL_ARGS_ASSERT_DO_OPEN_RAW;
424
425     /* For ease of blame back to 5.000, keep the existing indenting. */
426     {
427         /* sysopen style args, i.e. integer mode and permissions */
428         STRLEN ix = 0;
429         const int appendtrunc =
430              0
431 #ifdef O_APPEND /* Not fully portable. */
432              |O_APPEND
433 #endif
434 #ifdef O_TRUNC  /* Not fully portable. */
435              |O_TRUNC
436 #endif
437              ;
438         const int modifyingmode = O_WRONLY|O_RDWR|O_CREAT|appendtrunc;
439         int ismodifying;
440         SV *namesv;
441
442         /* It's not always
443
444            O_RDONLY 0
445            O_WRONLY 1
446            O_RDWR   2
447
448            It might be (in OS/390 and Mac OS Classic it is)
449
450            O_WRONLY 1
451            O_RDONLY 2
452            O_RDWR   3
453
454            This means that simple & with O_RDWR would look
455            like O_RDONLY is present.  Therefore we have to
456            be more careful.
457         */
458         if ((ismodifying = (rawmode & modifyingmode))) {
459              if ((ismodifying & O_WRONLY) == O_WRONLY ||
460                  (ismodifying & O_RDWR)   == O_RDWR   ||
461                  (ismodifying & (O_CREAT|appendtrunc)))
462                   TAINT_PROPER("sysopen");
463         }
464         mode[ix++] = IoTYPE_NUMERIC; /* Marker to openn to use numeric "sysopen" */
465
466 #if defined(USE_64_BIT_RAWIO) && defined(O_LARGEFILE)
467         rawmode |= O_LARGEFILE; /* Transparently largefiley. */
468 #endif
469
470         IoTYPE(io) = PerlIO_intmode2str(rawmode, &mode[ix], &writing);
471
472         namesv = newSVpvn_flags(oname, len, SVs_TEMP);
473         fp = PerlIO_openn(aTHX_ NULL, mode, -1, rawmode, rawperm, NULL, 1, &namesv);
474     }
475     return openn_cleanup(gv, io, fp, mode, oname, saveifp, saveofp, savefd,
476                          savetype, writing, 0, NULL, statbufp);
477 }
478
479 bool
480 Perl_do_open6(pTHX_ GV *gv, const char *oname, STRLEN len,
481               PerlIO *supplied_fp, SV **svp, U32 num_svs)
482 {
483     PerlIO *saveifp;
484     PerlIO *saveofp;
485     int savefd;
486     char savetype;
487     char mode[PERL_MODE_MAX];   /* file mode ("r\0", "rb\0", "ab\0" etc.) */
488     IO * const io = openn_setup(gv, mode, &saveifp, &saveofp, &savefd, &savetype);
489     int writing = 0;
490     PerlIO *fp;
491     bool was_fdopen = FALSE;
492     char *type  = NULL;
493
494     PERL_ARGS_ASSERT_DO_OPEN6;
495
496     /* For ease of blame back to 5.000, keep the existing indenting. */
497     {
498         /* Regular (non-sys) open */
499         char *name;
500         STRLEN olen = len;
501         char *tend;
502         int dodup = 0;
503         bool in_raw = 0, in_crlf = 0, out_raw = 0, out_crlf = 0;
504
505         /* Collect default raw/crlf info from the op */
506         if (PL_op && PL_op->op_type == OP_OPEN) {
507             /* set up IO layers */
508             const U8 flags = PL_op->op_private;
509             in_raw = (flags & OPpOPEN_IN_RAW);
510             in_crlf = (flags & OPpOPEN_IN_CRLF);
511             out_raw = (flags & OPpOPEN_OUT_RAW);
512             out_crlf = (flags & OPpOPEN_OUT_CRLF);
513         }
514
515         type = savepvn(oname, len);
516         tend = type+len;
517         SAVEFREEPV(type);
518
519         /* Lose leading and trailing white space */
520         while (isSPACE(*type))
521             type++;
522         while (tend > type && isSPACE(tend[-1]))
523             *--tend = '\0';
524
525         if (num_svs) {
526             const char *p;
527             STRLEN nlen = 0;
528             /* New style explicit name, type is just mode and layer info */
529 #ifdef USE_STDIO
530             if (SvROK(*svp) && !memchr(oname, '&', len)) {
531                 if (ckWARN(WARN_IO))
532                     Perl_warner(aTHX_ packWARN(WARN_IO),
533                             "Can't open a reference");
534                 SETERRNO(EINVAL, LIB_INVARG);
535                 fp = NULL;
536                 goto say_false;
537             }
538 #endif /* USE_STDIO */
539             p = (SvOK(*svp) || SvGMAGICAL(*svp)) ? SvPV(*svp, nlen) : NULL;
540
541             if (p && !IS_SAFE_PATHNAME(p, nlen, "open")) {
542                 fp = NULL;
543                 goto say_false;
544             }
545
546             name = p ? savepvn(p, nlen) : savepvs("");
547
548             SAVEFREEPV(name);
549         }
550         else {
551             name = type;
552             len  = tend-type;
553         }
554         IoTYPE(io) = *type;
555         if ((*type == IoTYPE_RDWR) && /* scary */
556            (*(type+1) == IoTYPE_RDONLY || *(type+1) == IoTYPE_WRONLY) &&
557             ((!num_svs || (tend > type+1 && tend[-1] != IoTYPE_PIPE)))) {
558             TAINT_PROPER("open");
559             mode[1] = *type++;
560             writing = 1;
561         }
562
563         if (*type == IoTYPE_PIPE) {
564             if (num_svs) {
565                 if (type[1] != IoTYPE_STD) {
566                   unknown_open_mode:
567                     Perl_croak(aTHX_ "Unknown open() mode '%.*s'", (int)olen, oname);
568                 }
569                 type++;
570             }
571             do {
572                 type++;
573             } while (isSPACE(*type));
574             if (!num_svs) {
575                 name = type;
576                 len = tend-type;
577             }
578             if (*name == '\0') {
579                 /* command is missing 19990114 */
580                 if (ckWARN(WARN_PIPE))
581                     Perl_warner(aTHX_ packWARN(WARN_PIPE), "Missing command in piped open");
582                 errno = EPIPE;
583                 fp = NULL;
584                 goto say_false;
585             }
586             if (!(*name == '-' && name[1] == '\0') || num_svs)
587                 TAINT_ENV();
588             TAINT_PROPER("piped open");
589             if (!num_svs && name[len-1] == '|') {
590                 name[--len] = '\0' ;
591                 if (ckWARN(WARN_PIPE))
592                     Perl_warner(aTHX_ packWARN(WARN_PIPE), "Can't open bidirectional pipe");
593             }
594             mode[0] = 'w';
595             writing = 1;
596             if (out_raw)
597                 mode[1] = 'b';
598             else if (out_crlf)
599                 mode[1] = 't';
600             if (num_svs > 1) {
601                 fp = PerlProc_popen_list(mode, num_svs, svp);
602             }
603             else {
604                 fp = PerlProc_popen(name,mode);
605             }
606             if (num_svs) {
607                 if (*type) {
608                     if (PerlIO_apply_layers(aTHX_ fp, mode, type) != 0) {
609                         fp = NULL;
610                         goto say_false;
611                     }
612                 }
613             }
614         } /* IoTYPE_PIPE */
615         else if (*type == IoTYPE_WRONLY) {
616             TAINT_PROPER("open");
617             type++;
618             if (*type == IoTYPE_WRONLY) {
619                 /* Two IoTYPE_WRONLYs in a row make for an IoTYPE_APPEND. */
620                 mode[0] = IoTYPE(io) = IoTYPE_APPEND;
621                 type++;
622             }
623             else {
624                 mode[0] = 'w';
625             }
626             writing = 1;
627
628             if (out_raw)
629                 mode[1] = 'b';
630             else if (out_crlf)
631                 mode[1] = 't';
632             if (*type == '&') {
633               duplicity:
634                 dodup = PERLIO_DUP_FD;
635                 type++;
636                 if (*type == '=') {
637                     dodup = 0;
638                     type++;
639                 }
640                 if (!num_svs && !*type && supplied_fp) {
641                     /* "<+&" etc. is used by typemaps */
642                     fp = supplied_fp;
643                 }
644                 else {
645                     PerlIO *that_fp = NULL;
646                     int wanted_fd;
647                     UV uv;
648                     if (num_svs > 1) {
649                         /* diag_listed_as: More than one argument to '%s' open */
650                         Perl_croak(aTHX_ "More than one argument to '%c&' open",IoTYPE(io));
651                     }
652                     while (isSPACE(*type))
653                         type++;
654                     if (num_svs && (
655                              SvIOK(*svp)
656                           || (SvPOKp(*svp) && looks_like_number(*svp))
657                        )) {
658                         wanted_fd = SvUV(*svp);
659                         num_svs = 0;
660                     }
661                     else if (isDIGIT(*type)
662                         && grok_atoUV(type, &uv, NULL)
663                         && uv <= INT_MAX
664                     ) {
665                         wanted_fd = (int)uv;
666                     }
667                     else {
668                         const IO* thatio;
669                         if (num_svs) {
670                             thatio = sv_2io(*svp);
671                         }
672                         else {
673                             GV * const thatgv = gv_fetchpvn_flags(type, tend - type,
674                                                        0, SVt_PVIO);
675                             thatio = GvIO(thatgv);
676                         }
677                         if (!thatio) {
678 #ifdef EINVAL
679                             SETERRNO(EINVAL,SS_IVCHAN);
680 #endif
681                             fp = NULL;
682                             goto say_false;
683                         }
684                         if ((that_fp = IoIFP(thatio))) {
685                             /* Flush stdio buffer before dup. --mjd
686                              * Unfortunately SEEK_CURing 0 seems to
687                              * be optimized away on most platforms;
688                              * only Solaris and Linux seem to flush
689                              * on that. --jhi */
690                             /* On the other hand, do all platforms
691                              * take gracefully to flushing a read-only
692                              * filehandle?  Perhaps we should do
693                              * fsetpos(src)+fgetpos(dst)?  --nik */
694                             PerlIO_flush(that_fp);
695                             wanted_fd = PerlIO_fileno(that_fp);
696                             /* When dup()ing STDIN, STDOUT or STDERR
697                              * explicitly set appropriate access mode */
698                             if (that_fp == PerlIO_stdout()
699                                 || that_fp == PerlIO_stderr())
700                                 IoTYPE(io) = IoTYPE_WRONLY;
701                             else if (that_fp == PerlIO_stdin())
702                                 IoTYPE(io) = IoTYPE_RDONLY;
703                             /* When dup()ing a socket, say result is
704                              * one as well */
705                             else if (IoTYPE(thatio) == IoTYPE_SOCKET)
706                                 IoTYPE(io) = IoTYPE_SOCKET;
707                         }
708                         else {
709                             SETERRNO(EBADF, RMS_IFI);
710                             fp = NULL;
711                             goto say_false;
712                         }
713                     }
714                     if (!num_svs)
715                         type = NULL;
716                     if (that_fp) {
717                         fp = PerlIO_fdupopen(aTHX_ that_fp, NULL, dodup);
718                     }
719                     else {
720                         if (dodup)
721                             wanted_fd = PerlLIO_dup_cloexec(wanted_fd);
722                         else
723                             was_fdopen = TRUE;
724                         if (!(fp = PerlIO_openn(aTHX_ type,mode,wanted_fd,0,0,NULL,num_svs,svp))) {
725                             if (dodup && wanted_fd >= 0)
726                                 PerlLIO_close(wanted_fd);
727                         }
728                     }
729                 }
730             } /* & */
731             else {
732                 while (isSPACE(*type))
733                     type++;
734                 if (*type == IoTYPE_STD && (!type[1] || isSPACE(type[1]) || type[1] == ':')) {
735                     type++;
736                     fp = PerlIO_stdout();
737                     IoTYPE(io) = IoTYPE_STD;
738                     if (num_svs > 1) {
739                         /* diag_listed_as: More than one argument to '%s' open */
740                         Perl_croak(aTHX_ "More than one argument to '>%c' open",IoTYPE_STD);
741                     }
742                 }
743                 else  {
744                     if (num_svs) {
745                         fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,num_svs,svp);
746                     }
747                     else {
748                         SV *namesv = newSVpvn_flags(type, tend - type, SVs_TEMP);
749                         type = NULL;
750                         fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,1,&namesv);
751                     }
752                 }
753             } /* !& */
754             if (!fp && type && *type && *type != ':' && !isIDFIRST(*type))
755                goto unknown_open_mode;
756         } /* IoTYPE_WRONLY */
757         else if (*type == IoTYPE_RDONLY) {
758             do {
759                 type++;
760             } while (isSPACE(*type));
761             mode[0] = 'r';
762             if (in_raw)
763                 mode[1] = 'b';
764             else if (in_crlf)
765                 mode[1] = 't';
766             if (*type == '&') {
767                 goto duplicity;
768             }
769             if (*type == IoTYPE_STD && (!type[1] || isSPACE(type[1]) || type[1] == ':')) {
770                 type++;
771                 fp = PerlIO_stdin();
772                 IoTYPE(io) = IoTYPE_STD;
773                 if (num_svs > 1) {
774                     /* diag_listed_as: More than one argument to '%s' open */
775                     Perl_croak(aTHX_ "More than one argument to '<%c' open",IoTYPE_STD);
776                 }
777             }
778             else {
779                 if (num_svs) {
780                     fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,num_svs,svp);
781                 }
782                 else {
783                     SV *namesv  = newSVpvn_flags(type, tend - type, SVs_TEMP);
784                     type = NULL;
785                     fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,1,&namesv);
786                 }
787             }
788             if (!fp && type && *type && *type != ':' && !isIDFIRST(*type))
789                goto unknown_open_mode;
790         } /* IoTYPE_RDONLY */
791         else if ((num_svs && /* '-|...' or '...|' */
792                   type[0] == IoTYPE_STD && type[1] == IoTYPE_PIPE) ||
793                  (!num_svs && tend > type+1 && tend[-1] == IoTYPE_PIPE)) {
794             if (num_svs) {
795                 type += 2;   /* skip over '-|' */
796             }
797             else {
798                 *--tend = '\0';
799                 while (tend > type && isSPACE(tend[-1]))
800                     *--tend = '\0';
801                 for (; isSPACE(*type); type++)
802                     ;
803                 name = type;
804                 len  = tend-type;
805             }
806             if (*name == '\0') {
807                 /* command is missing 19990114 */
808                 if (ckWARN(WARN_PIPE))
809                     Perl_warner(aTHX_ packWARN(WARN_PIPE), "Missing command in piped open");
810                 errno = EPIPE;
811                 fp = NULL;
812                 goto say_false;
813             }
814             if (!(*name == '-' && name[1] == '\0') || num_svs)
815                 TAINT_ENV();
816             TAINT_PROPER("piped open");
817             mode[0] = 'r';
818
819             if (in_raw)
820                 mode[1] = 'b';
821             else if (in_crlf)
822                 mode[1] = 't';
823
824             if (num_svs > 1) {
825                 fp = PerlProc_popen_list(mode,num_svs,svp);
826             }
827             else {
828                 fp = PerlProc_popen(name,mode);
829             }
830             IoTYPE(io) = IoTYPE_PIPE;
831             if (num_svs) {
832                 while (isSPACE(*type))
833                     type++;
834                 if (*type) {
835                     if (PerlIO_apply_layers(aTHX_ fp, mode, type) != 0) {
836                         fp = NULL;
837                         goto say_false;
838                     }
839                 }
840             }
841         }
842         else { /* layer(Args) */
843             if (num_svs)
844                 goto unknown_open_mode;
845             name = type;
846             IoTYPE(io) = IoTYPE_RDONLY;
847             for (; isSPACE(*name); name++)
848                 ;
849             mode[0] = 'r';
850
851             if (in_raw)
852                 mode[1] = 'b';
853             else if (in_crlf)
854                 mode[1] = 't';
855
856             if (*name == '-' && name[1] == '\0') {
857                 fp = PerlIO_stdin();
858                 IoTYPE(io) = IoTYPE_STD;
859             }
860             else {
861                 if (num_svs) {
862                     fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,num_svs,svp);
863                 }
864                 else {
865                     SV *namesv = newSVpvn_flags(type, tend - type, SVs_TEMP);
866                     type = NULL;
867                     fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,1,&namesv);
868                 }
869             }
870         }
871     }
872
873   say_false:
874     return openn_cleanup(gv, io, fp, mode, oname, saveifp, saveofp, savefd,
875                          savetype, writing, was_fdopen, type, NULL);
876 }
877
878 /* Yes, this is ugly, but it's private, and I don't see a cleaner way to
879    simplify the two-headed public interface of do_openn. */
880 static bool
881 S_openn_cleanup(pTHX_ GV *gv, IO *io, PerlIO *fp, char *mode, const char *oname,
882                 PerlIO *saveifp, PerlIO *saveofp, int savefd, char savetype,
883                 int writing, bool was_fdopen, const char *type, Stat_t *statbufp)
884 {
885     int fd;
886     Stat_t statbuf;
887
888     PERL_ARGS_ASSERT_OPENN_CLEANUP;
889
890     Zero(&statbuf, 1, Stat_t);
891
892     if (!fp) {
893         if (IoTYPE(io) == IoTYPE_RDONLY && ckWARN(WARN_NEWLINE)
894             && should_warn_nl(oname)
895             
896         )
897         {
898             GCC_DIAG_IGNORE_STMT(-Wformat-nonliteral); /* PL_warn_nl is constant */
899             Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "open");
900             GCC_DIAG_RESTORE_STMT;
901         }
902         goto say_false;
903     }
904
905     if (ckWARN(WARN_IO)) {
906         if ((IoTYPE(io) == IoTYPE_RDONLY) &&
907             (fp == PerlIO_stdout() || fp == PerlIO_stderr())) {
908                 Perl_warner(aTHX_ packWARN(WARN_IO),
909                             "Filehandle STD%s reopened as %" HEKf
910                             " only for input",
911                             ((fp == PerlIO_stdout()) ? "OUT" : "ERR"),
912                             HEKfARG(GvENAME_HEK(gv)));
913         }
914         else if ((IoTYPE(io) == IoTYPE_WRONLY) && fp == PerlIO_stdin()) {
915                 Perl_warner(aTHX_ packWARN(WARN_IO),
916                     "Filehandle STDIN reopened as %" HEKf " only for output",
917                      HEKfARG(GvENAME_HEK(gv))
918                 );
919         }
920     }
921
922     fd = PerlIO_fileno(fp);
923     /* Do NOT do: "if (fd < 0) goto say_false;" here.  If there is no
924      * fd assume it isn't a socket - this covers PerlIO::scalar -
925      * otherwise unless we "know" the type probe for socket-ness.
926      */
927     if (IoTYPE(io) && IoTYPE(io) != IoTYPE_PIPE && IoTYPE(io) != IoTYPE_STD && fd >= 0) {
928         if (PerlLIO_fstat(fd,&statbuf) < 0) {
929             /* If PerlIO claims to have fd we had better be able to fstat() it. */
930             (void) PerlIO_close(fp);
931             goto say_false;
932         }
933 #ifndef PERL_MICRO
934         if (S_ISSOCK(statbuf.st_mode))
935             IoTYPE(io) = IoTYPE_SOCKET; /* in case a socket was passed in to us */
936 #ifdef HAS_SOCKET
937         else if (
938             !(statbuf.st_mode & S_IFMT)
939             && IoTYPE(io) != IoTYPE_WRONLY  /* Dups of STD* filehandles already have */
940             && IoTYPE(io) != IoTYPE_RDONLY  /* type so they aren't marked as sockets */
941         ) {                                 /* on OS's that return 0 on fstat()ed pipe */
942              char tmpbuf[256];
943              Sock_size_t buflen = sizeof tmpbuf;
944              if (PerlSock_getsockname(fd, (struct sockaddr *)tmpbuf, &buflen) >= 0
945                       || errno != ENOTSOCK)
946                     IoTYPE(io) = IoTYPE_SOCKET; /* some OS's return 0 on fstat()ed socket */
947                                                 /* but some return 0 for streams too, sigh */
948         }
949 #endif /* HAS_SOCKET */
950 #endif /* !PERL_MICRO */
951     }
952
953     /* Eeek - FIXME !!!
954      * If this is a standard handle we discard all the layer stuff
955      * and just dup the fd into whatever was on the handle before !
956      */
957
958     if (saveifp) {              /* must use old fp? */
959         /* If fd is less that PL_maxsysfd i.e. STDIN..STDERR
960            then dup the new fileno down
961          */
962         if (saveofp) {
963             PerlIO_flush(saveofp);      /* emulate PerlIO_close() */
964             if (saveofp != saveifp) {   /* was a socket? */
965                 PerlIO_close(saveofp);
966             }
967         }
968         if (savefd != fd) {
969             /* Still a small can-of-worms here if (say) PerlIO::scalar
970                is assigned to (say) STDOUT - for now let dup2() fail
971                and provide the error
972              */
973             if (fd < 0) {
974                 SETERRNO(EBADF,RMS_IFI);
975                 goto say_false;
976             } else if (PerlLIO_dup2(fd, savefd) < 0) {
977                 (void)PerlIO_close(fp);
978                 goto say_false;
979             }
980 #ifdef VMS
981             if (savefd != PerlIO_fileno(PerlIO_stdin())) {
982                 char newname[FILENAME_MAX+1];
983                 if (PerlIO_getname(fp, newname)) {
984                     if (fd == PerlIO_fileno(PerlIO_stdout()))
985                         vmssetuserlnm("SYS$OUTPUT", newname);
986                     if (fd == PerlIO_fileno(PerlIO_stderr()))
987                         vmssetuserlnm("SYS$ERROR", newname);
988                 }
989             }
990 #endif
991
992 #if !defined(WIN32)
993            /* PL_fdpid isn't used on Windows, so avoid this useless work.
994             * XXX Probably the same for a lot of other places. */
995             {
996                 Pid_t pid;
997                 SV *sv;
998
999                 sv = *av_fetch(PL_fdpid,fd,TRUE);
1000                 SvUPGRADE(sv, SVt_IV);
1001                 pid = SvIVX(sv);
1002                 SvIV_set(sv, 0);
1003                 sv = *av_fetch(PL_fdpid,savefd,TRUE);
1004                 SvUPGRADE(sv, SVt_IV);
1005                 SvIV_set(sv, pid);
1006             }
1007 #endif
1008
1009             if (was_fdopen) {
1010                 /* need to close fp without closing underlying fd */
1011                 int ofd = PerlIO_fileno(fp);
1012                 int dupfd = ofd >= 0 ? PerlLIO_dup_cloexec(ofd) : -1;
1013                 if (ofd < 0 || dupfd < 0) {
1014                     if (dupfd >= 0)
1015                         PerlLIO_close(dupfd);
1016                     goto say_false;
1017                 }
1018                 PerlIO_close(fp);
1019                 PerlLIO_dup2_cloexec(dupfd, ofd);
1020                 setfd_inhexec_for_sysfd(ofd);
1021                 PerlLIO_close(dupfd);
1022             }
1023             else
1024                 PerlIO_close(fp);
1025         }
1026         fp = saveifp;
1027         PerlIO_clearerr(fp);
1028         fd = PerlIO_fileno(fp);
1029     }
1030     IoIFP(io) = fp;
1031
1032     IoFLAGS(io) &= ~IOf_NOLINE;
1033     if (writing) {
1034         if (IoTYPE(io) == IoTYPE_SOCKET
1035             || (IoTYPE(io) == IoTYPE_WRONLY && fd >= 0 && S_ISCHR(statbuf.st_mode)) ) {
1036             char *s = mode;
1037             if (*s == IoTYPE_IMPLICIT || *s == IoTYPE_NUMERIC)
1038               s++;
1039             *s = 'w';
1040             if (!(IoOFP(io) = PerlIO_openn(aTHX_ type,s,fd,0,0,NULL,0,NULL))) {
1041                 PerlIO_close(fp);
1042                 goto say_false;
1043             }
1044         }
1045         else
1046             IoOFP(io) = fp;
1047     }
1048     if (statbufp)
1049         *statbufp = statbuf;
1050
1051     return TRUE;
1052
1053   say_false:
1054     IoIFP(io) = saveifp;
1055     IoOFP(io) = saveofp;
1056     IoTYPE(io) = savetype;
1057     return FALSE;
1058 }
1059
1060 /* Open a temp file in the same directory as an original name.
1061 */
1062
1063 static bool
1064 S_openindirtemp(pTHX_ GV *gv, SV *orig_name, SV *temp_out_name) {
1065     int fd;
1066     PerlIO *fp;
1067     const char *p = SvPV_nolen(orig_name);
1068     const char *sep;
1069
1070     /* look for the last directory separator */
1071     sep = strrchr(p, '/');
1072
1073 #ifdef DOSISH
1074     {
1075         const char *sep2;
1076         if ((sep2 = strrchr(sep ? sep : p, '\\')))
1077             sep = sep2;
1078     }
1079 #endif
1080 #ifdef VMS
1081     if (!sep) {
1082         const char *openp = strchr(p, '[');
1083         if (openp)
1084             sep = strchr(openp, ']');
1085         else {
1086             sep = strchr(p, ':');
1087         }
1088     }
1089 #endif
1090     if (sep) {
1091         sv_setpvn(temp_out_name, p, sep - p + 1);
1092         sv_catpvs(temp_out_name, "XXXXXXXX");
1093     }
1094     else
1095         sv_setpvs(temp_out_name, "XXXXXXXX");
1096
1097     {
1098       int old_umask = umask(0177);
1099       fd = Perl_my_mkstemp_cloexec(SvPVX(temp_out_name));
1100       umask(old_umask);
1101     }
1102
1103     if (fd < 0)
1104         return FALSE;
1105
1106     fp = PerlIO_fdopen(fd, "w+");
1107     if (!fp)
1108         return FALSE;
1109
1110     return do_openn(gv, "+>&", 3, 0, 0, 0, fp, NULL, 0);
1111 }
1112
1113 #if defined(HAS_UNLINKAT) && defined(HAS_RENAMEAT) && defined(HAS_FCHMODAT) && \
1114     (defined(HAS_DIRFD) || defined(HAS_DIR_DD_FD)) && !defined(NO_USE_ATFUNCTIONS) && \
1115     defined(HAS_LINKAT)
1116 #  define ARGV_USE_ATFUNCTIONS
1117 #endif
1118
1119 /* Win32 doesn't necessarily return useful information
1120  * in st_dev, st_ino.
1121  */
1122 #ifndef DOSISH
1123 #  define ARGV_USE_STAT_INO
1124 #endif
1125
1126 #define ARGVMG_BACKUP_NAME 0
1127 #define ARGVMG_TEMP_NAME 1
1128 #define ARGVMG_ORIG_NAME 2
1129 #define ARGVMG_ORIG_MODE 3
1130 #define ARGVMG_ORIG_PID 4
1131
1132 /* we store the entire stat_t since the ino_t and dev_t values might
1133    not fit in an IV.  I could have created a new structure and
1134    transferred them across, but this seemed too much effort for very
1135    little win.
1136
1137    We store it even when the *at() functions are available, since
1138    while the C runtime might have definitions for these functions, the
1139    operating system or a specific filesystem might not implement them.
1140    eg. NetBSD 6 implements linkat() but only where the fds are AT_FDCWD.
1141  */
1142 #ifdef ARGV_USE_STAT_INO
1143 #  define ARGVMG_ORIG_CWD_STAT 5
1144 #endif
1145
1146 #ifdef ARGV_USE_ATFUNCTIONS
1147 #  define ARGVMG_ORIG_DIRP 6
1148 #endif
1149
1150 #ifdef ENOTSUP
1151 #define NotSupported(e) ((e) == ENOSYS || (e) == ENOTSUP)
1152 #else
1153 #define NotSupported(e) ((e) == ENOSYS)
1154 #endif
1155
1156 static int
1157 S_argvout_free(pTHX_ SV *io, MAGIC *mg) {
1158     PERL_UNUSED_ARG(io);
1159
1160     /* note this can be entered once the file has been
1161        successfully deleted too */
1162     assert(IoTYPE(io) != IoTYPE_PIPE);
1163
1164     /* mg_obj can be NULL if a thread is created with the handle open, in which
1165      case we leave any clean up to the parent thread */
1166     if (mg->mg_obj && IoIFP(io)) {
1167         SV **pid_psv;
1168 #ifdef ARGV_USE_ATFUNCTIONS
1169         SV **dir_psv;
1170         DIR *dir;
1171 #endif
1172         PerlIO *iop = IoIFP(io);
1173
1174         assert(SvTYPE(mg->mg_obj) == SVt_PVAV);
1175
1176         pid_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_ORIG_PID, FALSE);
1177
1178         assert(pid_psv && *pid_psv);
1179
1180         if (SvIV(*pid_psv) == (IV)PerlProc_getpid()) {
1181             /* if we get here the file hasn't been closed explicitly by the
1182                user and hadn't been closed implicitly by nextargv(), so
1183                abandon the edit */
1184             SV **temp_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_TEMP_NAME, FALSE);
1185             const char *temp_pv = SvPVX(*temp_psv);
1186
1187             assert(temp_psv && *temp_psv && SvPOK(*temp_psv));
1188             (void)PerlIO_close(iop);
1189             IoIFP(io) = IoOFP(io) = NULL;
1190 #ifdef ARGV_USE_ATFUNCTIONS
1191             dir_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_ORIG_DIRP, FALSE);
1192             assert(dir_psv && *dir_psv && SvIOK(*dir_psv));
1193             dir = INT2PTR(DIR *, SvIV(*dir_psv));
1194             if (dir) {
1195                 if (unlinkat(my_dirfd(dir), temp_pv, 0) < 0 &&
1196                     NotSupported(errno))
1197                     (void)UNLINK(temp_pv);
1198                 closedir(dir);
1199             }
1200 #else
1201             (void)UNLINK(temp_pv);
1202 #endif
1203         }
1204     }
1205
1206     return 0;
1207 }
1208
1209 static int
1210 S_argvout_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param) {
1211     PERL_UNUSED_ARG(param);
1212
1213     /* ideally we could just remove the magic from the SV but we don't get the SV here */
1214     SvREFCNT_dec(mg->mg_obj);
1215     mg->mg_obj = NULL;
1216
1217     return 0;
1218 }
1219
1220 /* Magic of this type has an AV containing the following:
1221    0: name of the backup file (if any)
1222    1: name of the temp output file
1223    2: name of the original file
1224    3: file mode of the original file
1225    4: pid of the process we opened at, to prevent doing the renaming
1226       etc in both the child and the parent after a fork
1227
1228 If we have useful inode/device ids in stat_t we also keep:
1229    5: a stat of the original current working directory
1230
1231 If we have unlinkat(), renameat(), fchmodat(), dirfd() we also keep:
1232    6: the DIR * for the current directory when we open the file, stored as an IV
1233  */
1234
1235 static const MGVTBL argvout_vtbl =
1236     {
1237         NULL, /* svt_get */
1238         NULL, /* svt_set */
1239         NULL, /* svt_len */
1240         NULL, /* svt_clear */
1241         S_argvout_free, /* svt_free */
1242         NULL, /* svt_copy */
1243         S_argvout_dup,  /* svt_dup */
1244         NULL /* svt_local */
1245     };
1246
1247 PerlIO *
1248 Perl_nextargv(pTHX_ GV *gv, bool nomagicopen)
1249 {
1250     IO * const io = GvIOp(gv);
1251     SV *const old_out_name = PL_inplace ? newSVsv(GvSV(gv)) : NULL;
1252
1253     PERL_ARGS_ASSERT_NEXTARGV;
1254
1255     if (old_out_name)
1256         SAVEFREESV(old_out_name);
1257
1258     if (!PL_argvoutgv)
1259         PL_argvoutgv = gv_fetchpvs("ARGVOUT", GV_ADD|GV_NOTQUAL, SVt_PVIO);
1260     if (io && (IoFLAGS(io) & (IOf_ARGV|IOf_START)) == (IOf_ARGV|IOf_START)) {
1261         IoFLAGS(io) &= ~IOf_START;
1262         if (PL_inplace) {
1263             assert(PL_defoutgv);
1264             Perl_av_create_and_push(aTHX_ &PL_argvout_stack,
1265                                     SvREFCNT_inc_simple_NN(PL_defoutgv));
1266         }
1267     }
1268
1269     {
1270         IO * const io = GvIOp(PL_argvoutgv);
1271         if (io && IoIFP(io) && old_out_name) {
1272             do_close(PL_argvoutgv, FALSE);
1273         }
1274     }
1275
1276     PL_lastfd = -1;
1277     PL_filemode = 0;
1278     if (!GvAV(gv))
1279         return NULL;
1280     while (av_tindex(GvAV(gv)) >= 0) {
1281         STRLEN oldlen;
1282         SV *const sv = av_shift(GvAV(gv));
1283         SAVEFREESV(sv);
1284         SvTAINTED_off(GvSVn(gv)); /* previous tainting irrelevant */
1285         sv_setsv(GvSVn(gv),sv);
1286         SvSETMAGIC(GvSV(gv));
1287         PL_oldname = SvPVx(GvSV(gv), oldlen);
1288         if (LIKELY(!PL_inplace)) {
1289             if (nomagicopen
1290                     ? do_open6(gv, "<", 1, NULL, &GvSV(gv), 1)
1291                     : do_open6(gv, PL_oldname, oldlen, NULL, NULL, 0)
1292                ) {
1293                 return IoIFP(GvIOp(gv));
1294             }
1295         }
1296         else {
1297             Stat_t statbuf;
1298             /* This very long block ends with return IoIFP(GvIOp(gv));
1299                Both this block and the block above fall through on open
1300                failure to the warning code, and then the while loop above tries
1301                the next entry. */
1302             if (do_open_raw(gv, PL_oldname, oldlen, O_RDONLY, 0, &statbuf)) {
1303 #ifndef FLEXFILENAMES
1304                 int filedev;
1305                 int fileino;
1306 #endif
1307 #ifdef ARGV_USE_ATFUNCTIONS
1308                 DIR *curdir;
1309 #endif
1310                 Uid_t fileuid;
1311                 Gid_t filegid;
1312                 AV *magic_av = NULL;
1313                 SV *temp_name_sv = NULL;
1314                 MAGIC *mg;
1315
1316                 TAINT_PROPER("inplace open");
1317                 if (oldlen == 1 && *PL_oldname == '-') {
1318                     setdefout(gv_fetchpvs("STDOUT", GV_ADD|GV_NOTQUAL,
1319                                           SVt_PVIO));
1320                     return IoIFP(GvIOp(gv));
1321                 }
1322 #ifndef FLEXFILENAMES
1323                 filedev = statbuf.st_dev;
1324                 fileino = statbuf.st_ino;
1325 #endif
1326                 PL_filemode = statbuf.st_mode;
1327                 fileuid = statbuf.st_uid;
1328                 filegid = statbuf.st_gid;
1329                 if (!S_ISREG(PL_filemode)) {
1330                     Perl_ck_warner_d(aTHX_ packWARN(WARN_INPLACE),
1331                                      "Can't do inplace edit: %s is not a regular file",
1332                                      PL_oldname );
1333                     do_close(gv,FALSE);
1334                     continue;
1335                 }
1336                 magic_av = newAV();
1337                 if (*PL_inplace && strNE(PL_inplace, "*")) {
1338                     const char *star = strchr(PL_inplace, '*');
1339                     if (star) {
1340                         const char *begin = PL_inplace;
1341                         SvPVCLEAR(sv);
1342                         do {
1343                             sv_catpvn(sv, begin, star - begin);
1344                             sv_catpvn(sv, PL_oldname, oldlen);
1345                             begin = ++star;
1346                         } while ((star = strchr(begin, '*')));
1347                         if (*begin)
1348                             sv_catpv(sv,begin);
1349                     }
1350                     else {
1351                         sv_catpv(sv,PL_inplace);
1352                     }
1353 #ifndef FLEXFILENAMES
1354                     if ((PerlLIO_stat(SvPVX_const(sv),&statbuf) >= 0
1355                          && statbuf.st_dev == filedev
1356                          && statbuf.st_ino == fileino)
1357 #ifdef DJGPP
1358                         || ((_djstat_fail_bits & _STFAIL_TRUENAME)!=0)
1359 #endif
1360                       )
1361                     {
1362                         Perl_ck_warner_d(aTHX_ packWARN(WARN_INPLACE),
1363                                          "Can't do inplace edit: %"
1364                                          SVf " would not be unique",
1365                                          SVfARG(sv));
1366                         goto cleanup_argv;
1367                     }
1368 #endif
1369                     av_store(magic_av, ARGVMG_BACKUP_NAME, newSVsv(sv));
1370                 }
1371
1372                 sv_setpvn(sv,PL_oldname,oldlen);
1373                 SETERRNO(0,0);          /* in case sprintf set errno */
1374                 temp_name_sv = newSV(0);
1375                 if (!S_openindirtemp(aTHX_ PL_argvoutgv, GvSV(gv), temp_name_sv)) {
1376                     SvREFCNT_dec(temp_name_sv);
1377                     /* diag_listed_as: Can't do inplace edit on %s: %s */
1378                     Perl_ck_warner_d(aTHX_ packWARN(WARN_INPLACE), "Can't do inplace edit on %s: Cannot make temp name: %s",
1379                                      PL_oldname, Strerror(errno) );
1380 #ifndef FLEXFILENAMES
1381                 cleanup_argv:
1382 #endif
1383                     do_close(gv,FALSE);
1384                     SvREFCNT_dec(magic_av);
1385                     continue;
1386                 }
1387                 av_store(magic_av, ARGVMG_TEMP_NAME, temp_name_sv);
1388                 av_store(magic_av, ARGVMG_ORIG_NAME, newSVsv(sv));
1389                 av_store(magic_av, ARGVMG_ORIG_MODE, newSVuv(PL_filemode));
1390                 av_store(magic_av, ARGVMG_ORIG_PID, newSViv((IV)PerlProc_getpid()));
1391 #if defined(ARGV_USE_ATFUNCTIONS)
1392                 curdir = opendir(".");
1393                 av_store(magic_av, ARGVMG_ORIG_DIRP, newSViv(PTR2IV(curdir)));
1394 #elif defined(ARGV_USE_STAT_INO)
1395                 if (PerlLIO_stat(".", &statbuf) >= 0) {
1396                     av_store(magic_av, ARGVMG_ORIG_CWD_STAT,
1397                              newSVpvn((char *)&statbuf, sizeof(statbuf)));
1398                 }
1399 #endif
1400                 setdefout(PL_argvoutgv);
1401                 sv_setsv(GvSVn(PL_argvoutgv), temp_name_sv);
1402                 mg = sv_magicext((SV*)GvIOp(PL_argvoutgv), (SV*)magic_av, PERL_MAGIC_uvar, &argvout_vtbl, NULL, 0);
1403                 mg->mg_flags |= MGf_DUP;
1404                 SvREFCNT_dec(magic_av);
1405                 PL_lastfd = PerlIO_fileno(IoIFP(GvIOp(PL_argvoutgv)));
1406                 if (PL_lastfd >= 0) {
1407                     (void)PerlLIO_fstat(PL_lastfd,&statbuf);
1408 #ifdef HAS_FCHMOD
1409                     (void)fchmod(PL_lastfd,PL_filemode);
1410 #else
1411                     (void)PerlLIO_chmod(PL_oldname,PL_filemode);
1412 #endif
1413                     if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) {
1414                         /* XXX silently ignore failures */
1415 #ifdef HAS_FCHOWN
1416                         PERL_UNUSED_RESULT(fchown(PL_lastfd,fileuid,filegid));
1417 #elif defined(HAS_CHOWN)
1418                         PERL_UNUSED_RESULT(PerlLIO_chown(PL_oldname,fileuid,filegid));
1419 #endif
1420                     }
1421                 }
1422                 return IoIFP(GvIOp(gv));
1423             }
1424         } /* successful do_open_raw(), PL_inplace non-NULL */
1425
1426         if (ckWARN_d(WARN_INPLACE)) {
1427             const int eno = errno;
1428             Stat_t statbuf;
1429             if (PerlLIO_stat(PL_oldname, &statbuf) >= 0
1430                 && !S_ISREG(statbuf.st_mode)) {
1431                 Perl_warner(aTHX_ packWARN(WARN_INPLACE),
1432                             "Can't do inplace edit: %s is not a regular file",
1433                             PL_oldname);
1434             }
1435             else {
1436                 Perl_warner(aTHX_ packWARN(WARN_INPLACE), "Can't open %s: %s",
1437                             PL_oldname, Strerror(eno));
1438             }
1439         }
1440     }
1441     if (io && (IoFLAGS(io) & IOf_ARGV))
1442         IoFLAGS(io) |= IOf_START;
1443     if (PL_inplace) {
1444         if (io && (IoFLAGS(io) & IOf_ARGV)
1445             && PL_argvout_stack && AvFILLp(PL_argvout_stack) >= 0)
1446         {
1447             GV * const oldout = MUTABLE_GV(av_pop(PL_argvout_stack));
1448             setdefout(oldout);
1449             SvREFCNT_dec_NN(oldout);
1450             return NULL;
1451         }
1452         setdefout(gv_fetchpvs("STDOUT", GV_ADD|GV_NOTQUAL, SVt_PVIO));
1453     }
1454     return NULL;
1455 }
1456
1457 #ifdef ARGV_USE_ATFUNCTIONS
1458 #  if defined(__FreeBSD__)
1459
1460 /* FreeBSD 11 renameat() mis-behaves strangely with absolute paths in cases where the
1461  * equivalent rename() succeeds
1462  */
1463 static int
1464 S_my_renameat(int olddfd, const char *oldpath, int newdfd, const char *newpath) {
1465     /* this is intended only for use in Perl_do_close() */
1466     assert(olddfd == newdfd);
1467     assert(PERL_FILE_IS_ABSOLUTE(oldpath) == PERL_FILE_IS_ABSOLUTE(newpath));
1468     if (PERL_FILE_IS_ABSOLUTE(oldpath)) {
1469         return PerlLIO_rename(oldpath, newpath);
1470     }
1471     else {
1472         return renameat(olddfd, oldpath, newdfd, newpath);
1473     }
1474 }
1475
1476 #  else
1477 #    define S_my_renameat(dh1, pv1, dh2, pv2) renameat((dh1), (pv1), (dh2), (pv2))
1478 #  endif /* if defined(__FreeBSD__) */
1479 #endif
1480
1481 static bool
1482 S_dir_unchanged(pTHX_ const char *orig_pv, MAGIC *mg) {
1483     Stat_t statbuf;
1484
1485 #ifdef ARGV_USE_STAT_INO
1486     SV **stat_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_ORIG_CWD_STAT, FALSE);
1487     Stat_t *orig_cwd_stat = stat_psv && *stat_psv ? (Stat_t *)SvPVX(*stat_psv) : NULL;
1488
1489     /* if the path is absolute the possible moving of cwd (which the file
1490        might be in) isn't our problem.
1491        This code tries to be reasonably balanced about detecting a changed
1492        CWD, if we have the information needed to check that curdir has changed, we
1493        check it
1494     */
1495     if (!PERL_FILE_IS_ABSOLUTE(orig_pv)
1496         && orig_cwd_stat
1497         && PerlLIO_stat(".", &statbuf) >= 0
1498         && ( statbuf.st_dev != orig_cwd_stat->st_dev
1499                      || statbuf.st_ino != orig_cwd_stat->st_ino)) {
1500         Perl_croak(aTHX_ "Cannot complete in-place edit of %s: %s",
1501                    orig_pv, "Current directory has changed");
1502     }
1503 #else
1504     SV **temp_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_TEMP_NAME, FALSE);
1505
1506     /* Some platforms don't have useful st_ino etc, so just
1507        check we can see the work file.
1508     */
1509     if (!PERL_FILE_IS_ABSOLUTE(orig_pv)
1510         && PerlLIO_stat(SvPVX(*temp_psv), &statbuf) < 0) {
1511         Perl_croak(aTHX_ "Cannot complete in-place edit of %s: %s",
1512                    orig_pv,
1513                    "Work file is missing - did you change directory?");
1514     }
1515 #endif
1516
1517     return TRUE;
1518 }
1519
1520 #define dir_unchanged(orig_psv, mg) \
1521     S_dir_unchanged(aTHX_ (orig_psv), (mg))
1522
1523 /* explicit renamed to avoid C++ conflict    -- kja */
1524 bool
1525 Perl_do_close(pTHX_ GV *gv, bool not_implicit)
1526 {
1527     bool retval;
1528     IO *io;
1529     MAGIC *mg;
1530
1531     if (!gv)
1532         gv = PL_argvgv;
1533     if (!gv || !isGV_with_GP(gv)) {
1534         if (not_implicit)
1535             SETERRNO(EBADF,SS_IVCHAN);
1536         return FALSE;
1537     }
1538     io = GvIO(gv);
1539     if (!io) {          /* never opened */
1540         if (not_implicit) {
1541             report_evil_fh(gv);
1542             SETERRNO(EBADF,SS_IVCHAN);
1543         }
1544         return FALSE;
1545     }
1546     if ((mg = mg_findext((SV*)io, PERL_MAGIC_uvar, &argvout_vtbl))
1547         && mg->mg_obj) {
1548         /* handle to an in-place edit work file */
1549         SV **back_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_BACKUP_NAME, FALSE);
1550         SV **temp_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_TEMP_NAME, FALSE);
1551         /* PL_oldname may have been modified by a nested ARGV use at this point */
1552         SV **orig_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_ORIG_NAME, FALSE);
1553         SV **mode_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_ORIG_MODE, FALSE);
1554         SV **pid_psv  = av_fetch((AV*)mg->mg_obj, ARGVMG_ORIG_PID, FALSE);
1555 #if defined(ARGV_USE_ATFUNCTIONS)
1556         SV **dir_psv  = av_fetch((AV*)mg->mg_obj, ARGVMG_ORIG_DIRP, FALSE);
1557         DIR *dir;
1558         int dfd;
1559 #endif
1560         UV mode;
1561         int fd;
1562
1563         const char *orig_pv;
1564
1565         assert(temp_psv && *temp_psv);
1566         assert(orig_psv && *orig_psv);
1567         assert(mode_psv && *mode_psv);
1568         assert(pid_psv && *pid_psv);
1569 #ifdef ARGV_USE_ATFUNCTIONS
1570         assert(dir_psv && *dir_psv);
1571         dir = INT2PTR(DIR *, SvIVX(*dir_psv));
1572         dfd = my_dirfd(dir);
1573 #endif
1574
1575         orig_pv = SvPVX(*orig_psv);
1576         mode = SvUV(*mode_psv);
1577
1578         if ((mode & (S_ISUID|S_ISGID)) != 0
1579             && (fd = PerlIO_fileno(IoIFP(io))) >= 0) {
1580             (void)PerlIO_flush(IoIFP(io));
1581 #ifdef HAS_FCHMOD
1582             (void)fchmod(fd, mode);
1583 #else
1584             (void)PerlLIO_chmod(orig_pv, mode);
1585 #endif
1586         }
1587
1588         retval = io_close(io, NULL, not_implicit, FALSE);
1589
1590         if (SvIV(*pid_psv) != (IV)PerlProc_getpid()) {
1591             /* this is a child process, don't duplicate our rename() etc
1592                processing below */
1593             goto freext;
1594         }
1595
1596         if (retval) {
1597 #if defined(DOSISH) || defined(__CYGWIN__)
1598             if (PL_argvgv && GvIOp(PL_argvgv)
1599                 && IoIFP(GvIOp(PL_argvgv))
1600                 && (IoFLAGS(GvIOp(PL_argvgv)) & (IOf_ARGV|IOf_START)) == IOf_ARGV) {
1601                 do_close(PL_argvgv, FALSE);
1602             }
1603 #endif
1604 #ifndef ARGV_USE_ATFUNCTIONS
1605             if (!dir_unchanged(orig_pv, mg))
1606                 goto abort_inplace;
1607 #endif
1608             if (back_psv && *back_psv) {
1609 #if defined(HAS_LINK) && !defined(DOSISH) && !defined(__CYGWIN__) && defined(HAS_RENAME)
1610                 if (
1611 #  ifdef ARGV_USE_ATFUNCTIONS
1612                     linkat(dfd, orig_pv, dfd, SvPVX(*back_psv), 0) < 0 &&
1613                     !(UNLIKELY(NotSupported(errno)) &&
1614                       dir_unchanged(orig_pv, mg) &&
1615                                link(orig_pv, SvPVX(*back_psv)) == 0)
1616 #  else
1617                     link(orig_pv, SvPVX(*back_psv)) < 0
1618 #  endif
1619                     )
1620 #endif
1621                 {
1622 #ifdef HAS_RENAME
1623                     if (
1624 #  ifdef ARGV_USE_ATFUNCTIONS
1625                         S_my_renameat(dfd, orig_pv, dfd, SvPVX(*back_psv)) < 0 &&
1626                         !(UNLIKELY(NotSupported(errno)) &&
1627                           dir_unchanged(orig_pv, mg) &&
1628                           PerlLIO_rename(orig_pv, SvPVX(*back_psv)) == 0)
1629 #  else
1630                         PerlLIO_rename(orig_pv, SvPVX(*back_psv)) < 0
1631 #  endif
1632                         ) {
1633                         if (!not_implicit) {
1634 #  ifdef ARGV_USE_ATFUNCTIONS
1635                             if (unlinkat(dfd, SvPVX_const(*temp_psv), 0) < 0 &&
1636                                 UNLIKELY(NotSupported(errno)) &&
1637                                 dir_unchanged(orig_pv, mg))
1638                                 (void)UNLINK(SvPVX_const(*temp_psv));
1639 #  else
1640                             UNLINK(SvPVX(*temp_psv));
1641 #  endif
1642                             Perl_croak(aTHX_ "Can't rename %s to %s: %s, skipping file",
1643                                        SvPVX(*orig_psv), SvPVX(*back_psv), Strerror(errno));
1644                         }
1645                         /* should we warn here? */
1646                         goto abort_inplace;
1647                     }
1648 #else
1649                     (void)UNLINK(SvPVX(*back_psv));
1650                     if (link(orig_pv, SvPVX(*back_psv))) {
1651                         if (!not_implicit) {
1652                             Perl_croak(aTHX_ "Can't rename %s to %s: %s, skipping file",
1653                                        SvPVX(*orig_psv), SvPVX(*back_psv), Strerror(errno));
1654                         }
1655                         goto abort_inplace;
1656                     }
1657                     /* we need to use link() to get the temp into place too, and linK()
1658                        fails if the new link name exists */
1659                     (void)UNLINK(orig_pv);
1660 #endif
1661                 }
1662             }
1663 #if defined(DOSISH) || defined(__CYGWIN__) || !defined(HAS_RENAME)
1664             else {
1665                 UNLINK(orig_pv);
1666             }
1667 #endif
1668             if (
1669 #if !defined(HAS_RENAME)
1670                 link(SvPVX(*temp_psv), orig_pv) < 0
1671 #elif defined(ARGV_USE_ATFUNCTIONS)
1672                 S_my_renameat(dfd, SvPVX(*temp_psv), dfd, orig_pv) < 0 &&
1673                 !(UNLIKELY(NotSupported(errno)) &&
1674                   dir_unchanged(orig_pv, mg) &&
1675                   PerlLIO_rename(SvPVX(*temp_psv), orig_pv) == 0)
1676 #else
1677                 PerlLIO_rename(SvPVX(*temp_psv), orig_pv) < 0
1678 #endif
1679                 ) {
1680                 if (!not_implicit) {
1681 #ifdef ARGV_USE_ATFUNCTIONS
1682                     if (unlinkat(dfd, SvPVX_const(*temp_psv), 0) < 0 &&
1683                         NotSupported(errno))
1684                         UNLINK(SvPVX(*temp_psv));
1685 #else
1686                     UNLINK(SvPVX(*temp_psv));
1687 #endif
1688                     /* diag_listed_as: Cannot complete in-place edit of %s: %s */
1689                     Perl_croak(aTHX_ "Cannot complete in-place edit of %s: failed to rename work file '%s' to '%s': %s",
1690                                orig_pv, SvPVX(*temp_psv), orig_pv, Strerror(errno));
1691                 }
1692             abort_inplace:
1693                 UNLINK(SvPVX_const(*temp_psv));
1694                 retval = FALSE;
1695             }
1696 #ifndef HAS_RENAME
1697             UNLINK(SvPVX(*temp_psv));
1698 #endif
1699         }
1700         else {
1701 #ifdef ARGV_USE_ATFUNCTIONS
1702             if (unlinkat(dfd, SvPVX_const(*temp_psv), 0) &&
1703                 NotSupported(errno))
1704                 UNLINK(SvPVX_const(*temp_psv));
1705                 
1706 #else
1707             UNLINK(SvPVX_const(*temp_psv));
1708 #endif
1709             if (!not_implicit) {
1710                 Perl_croak(aTHX_ "Failed to close in-place work file %s: %s",
1711                            SvPVX(*temp_psv), Strerror(errno));
1712             }
1713         }
1714     freext:
1715         mg_freeext((SV*)io, PERL_MAGIC_uvar, &argvout_vtbl);
1716     }
1717     else {
1718         retval = io_close(io, NULL, not_implicit, FALSE);
1719     }
1720     if (not_implicit) {
1721         IoLINES(io) = 0;
1722         IoPAGE(io) = 0;
1723         IoLINES_LEFT(io) = IoPAGE_LEN(io);
1724     }
1725     IoTYPE(io) = IoTYPE_CLOSED;
1726     return retval;
1727 }
1728
1729 bool
1730 Perl_io_close(pTHX_ IO *io, GV *gv, bool not_implicit, bool warn_on_fail)
1731 {
1732     bool retval = FALSE;
1733
1734     PERL_ARGS_ASSERT_IO_CLOSE;
1735
1736     if (IoIFP(io)) {
1737         if (IoTYPE(io) == IoTYPE_PIPE) {
1738             const int status = PerlProc_pclose(IoIFP(io));
1739             if (not_implicit) {
1740                 STATUS_NATIVE_CHILD_SET(status);
1741                 retval = (STATUS_UNIX == 0);
1742             }
1743             else {
1744                 retval = (status != -1);
1745             }
1746         }
1747         else if (IoTYPE(io) == IoTYPE_STD)
1748             retval = TRUE;
1749         else {
1750             if (IoOFP(io) && IoOFP(io) != IoIFP(io)) {          /* a socket */
1751                 const bool prev_err = PerlIO_error(IoOFP(io));
1752 #ifdef USE_PERLIO
1753                 if (prev_err)
1754                     PerlIO_restore_errno(IoOFP(io));
1755 #endif
1756                 retval = (PerlIO_close(IoOFP(io)) != EOF && !prev_err);
1757                 PerlIO_close(IoIFP(io));        /* clear stdio, fd already closed */
1758             }
1759             else {
1760                 const bool prev_err = PerlIO_error(IoIFP(io));
1761 #ifdef USE_PERLIO
1762                 if (prev_err)
1763                     PerlIO_restore_errno(IoIFP(io));
1764 #endif
1765                 retval = (PerlIO_close(IoIFP(io)) != EOF && !prev_err);
1766             }
1767         }
1768         IoOFP(io) = IoIFP(io) = NULL;
1769
1770         if (warn_on_fail && !retval) {
1771             if (gv)
1772                 Perl_ck_warner_d(aTHX_ packWARN(WARN_IO),
1773                                 "Warning: unable to close filehandle %"
1774                                  HEKf " properly: %" SVf,
1775                                  HEKfARG(GvNAME_HEK(gv)),
1776                                  SVfARG(get_sv("!",GV_ADD)));
1777             else
1778                 Perl_ck_warner_d(aTHX_ packWARN(WARN_IO),
1779                                 "Warning: unable to close filehandle "
1780                                 "properly: %" SVf,
1781                                  SVfARG(get_sv("!",GV_ADD)));
1782         }
1783     }
1784     else if (not_implicit) {
1785         SETERRNO(EBADF,SS_IVCHAN);
1786     }
1787
1788     return retval;
1789 }
1790
1791 bool
1792 Perl_do_eof(pTHX_ GV *gv)
1793 {
1794     IO * const io = GvIO(gv);
1795
1796     PERL_ARGS_ASSERT_DO_EOF;
1797
1798     if (!io)
1799         return TRUE;
1800     else if (IoTYPE(io) == IoTYPE_WRONLY)
1801         report_wrongway_fh(gv, '>');
1802
1803     while (IoIFP(io)) {
1804         if (PerlIO_has_cntptr(IoIFP(io))) {     /* (the code works without this) */
1805             if (PerlIO_get_cnt(IoIFP(io)) > 0)  /* cheat a little, since */
1806                 return FALSE;                   /* this is the most usual case */
1807         }
1808
1809         {
1810              /* getc and ungetc can stomp on errno */
1811             dSAVE_ERRNO;
1812             const int ch = PerlIO_getc(IoIFP(io));
1813             if (ch != EOF) {
1814                 (void)PerlIO_ungetc(IoIFP(io),ch);
1815                 RESTORE_ERRNO;
1816                 return FALSE;
1817             }
1818             RESTORE_ERRNO;
1819         }
1820
1821         if (PerlIO_has_cntptr(IoIFP(io)) && PerlIO_canset_cnt(IoIFP(io))) {
1822             if (PerlIO_get_cnt(IoIFP(io)) < -1)
1823                 PerlIO_set_cnt(IoIFP(io),-1);
1824         }
1825         if (PL_op->op_flags & OPf_SPECIAL) { /* not necessarily a real EOF yet? */
1826             if (gv != PL_argvgv || !nextargv(gv, FALSE))        /* get another fp handy */
1827                 return TRUE;
1828         }
1829         else
1830             return TRUE;                /* normal fp, definitely end of file */
1831     }
1832     return TRUE;
1833 }
1834
1835 Off_t
1836 Perl_do_tell(pTHX_ GV *gv)
1837 {
1838     IO *const io = GvIO(gv);
1839     PerlIO *fp;
1840
1841     PERL_ARGS_ASSERT_DO_TELL;
1842
1843     if (io && (fp = IoIFP(io))) {
1844         return PerlIO_tell(fp);
1845     }
1846     report_evil_fh(gv);
1847     SETERRNO(EBADF,RMS_IFI);
1848     return (Off_t)-1;
1849 }
1850
1851 bool
1852 Perl_do_seek(pTHX_ GV *gv, Off_t pos, int whence)
1853 {
1854     IO *const io = GvIO(gv);
1855     PerlIO *fp;
1856
1857     if (io && (fp = IoIFP(io))) {
1858         return PerlIO_seek(fp, pos, whence) >= 0;
1859     }
1860     report_evil_fh(gv);
1861     SETERRNO(EBADF,RMS_IFI);
1862     return FALSE;
1863 }
1864
1865 Off_t
1866 Perl_do_sysseek(pTHX_ GV *gv, Off_t pos, int whence)
1867 {
1868     IO *const io = GvIO(gv);
1869     PerlIO *fp;
1870
1871     PERL_ARGS_ASSERT_DO_SYSSEEK;
1872
1873     if (io && (fp = IoIFP(io))) {
1874         int fd = PerlIO_fileno(fp);
1875         if (fd < 0 || (whence == SEEK_SET && pos < 0)) {
1876             SETERRNO(EINVAL,LIB_INVARG);
1877             return -1;
1878         } else {
1879             return PerlLIO_lseek(fd, pos, whence);
1880         }
1881     }
1882     report_evil_fh(gv);
1883     SETERRNO(EBADF,RMS_IFI);
1884     return (Off_t)-1;
1885 }
1886
1887 int
1888 Perl_mode_from_discipline(pTHX_ const char *s, STRLEN len)
1889 {
1890     int mode = O_BINARY;
1891     PERL_UNUSED_CONTEXT;
1892     if (s) {
1893         while (*s) {
1894             if (*s == ':') {
1895                 switch (s[1]) {
1896                 case 'r':
1897                     if (s[2] == 'a' && s[3] == 'w'
1898                         && (!s[4] || s[4] == ':' || isSPACE(s[4])))
1899                     {
1900                         mode = O_BINARY;
1901                         s += 4;
1902                         len -= 4;
1903                         break;
1904                     }
1905                     /* FALLTHROUGH */
1906                 case 'c':
1907                     if (s[2] == 'r' && s[3] == 'l' && s[4] == 'f'
1908                         && (!s[5] || s[5] == ':' || isSPACE(s[5])))
1909                     {
1910                         mode = O_TEXT;
1911                         s += 5;
1912                         len -= 5;
1913                         break;
1914                     }
1915                     /* FALLTHROUGH */
1916                 default:
1917                     goto fail_discipline;
1918                 }
1919             }
1920             else if (isSPACE(*s)) {
1921                 ++s;
1922                 --len;
1923             }
1924             else {
1925                 const char *end;
1926   fail_discipline:
1927                 end = (char *) memchr(s+1, ':', len);
1928                 if (!end)
1929                     end = s+len;
1930 #ifndef PERLIO_LAYERS
1931                 Perl_croak(aTHX_ "IO layers (like '%.*s') unavailable", end-s, s);
1932 #else
1933                 len -= end-s;
1934                 s = end;
1935 #endif
1936             }
1937         }
1938     }
1939     return mode;
1940 }
1941
1942 #if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE)
1943 I32
1944 my_chsize(int fd, Off_t length)
1945 {
1946 #ifdef F_FREESP
1947         /* code courtesy of William Kucharski */
1948 #define HAS_CHSIZE
1949
1950     Stat_t filebuf;
1951
1952     if (PerlLIO_fstat(fd, &filebuf) < 0)
1953         return -1;
1954
1955     if (filebuf.st_size < length) {
1956
1957         /* extend file length */
1958
1959         if ((PerlLIO_lseek(fd, (length - 1), 0)) < 0)
1960             return -1;
1961
1962         /* write a "0" byte */
1963
1964         if ((PerlLIO_write(fd, "", 1)) != 1)
1965             return -1;
1966     }
1967     else {
1968         /* truncate length */
1969         struct flock fl;
1970         fl.l_whence = 0;
1971         fl.l_len = 0;
1972         fl.l_start = length;
1973         fl.l_type = F_WRLCK;    /* write lock on file space */
1974
1975         /*
1976         * This relies on the UNDOCUMENTED F_FREESP argument to
1977         * fcntl(2), which truncates the file so that it ends at the
1978         * position indicated by fl.l_start.
1979         *
1980         * Will minor miracles never cease?
1981         */
1982
1983         if (fcntl(fd, F_FREESP, &fl) < 0)
1984             return -1;
1985
1986     }
1987     return 0;
1988 #else
1989     Perl_croak_nocontext("truncate not implemented");
1990 #endif /* F_FREESP */
1991     return -1;
1992 }
1993 #endif /* !HAS_TRUNCATE && !HAS_CHSIZE */
1994
1995 bool
1996 Perl_do_print(pTHX_ SV *sv, PerlIO *fp)
1997 {
1998     PERL_ARGS_ASSERT_DO_PRINT;
1999
2000     /* assuming fp is checked earlier */
2001     if (!sv)
2002         return TRUE;
2003     if (SvTYPE(sv) == SVt_IV && SvIOK(sv)) {
2004         assert(!SvGMAGICAL(sv));
2005         if (SvIsUV(sv))
2006             PerlIO_printf(fp, "%" UVuf, (UV)SvUVX(sv));
2007         else
2008             PerlIO_printf(fp, "%" IVdf, (IV)SvIVX(sv));
2009         return !PerlIO_error(fp);
2010     }
2011     else {
2012         STRLEN len;
2013         /* Do this first to trigger any overloading.  */
2014         const char *tmps = SvPV_const(sv, len);
2015         U8 *tmpbuf = NULL;
2016         bool happy = TRUE;
2017
2018         if (PerlIO_isutf8(fp)) { /* If the stream is utf8 ... */
2019             if (!SvUTF8(sv)) {  /* Convert to utf8 if necessary */
2020                 /* We don't modify the original scalar.  */
2021                 tmpbuf = bytes_to_utf8((const U8*) tmps, &len);
2022                 tmps = (char *) tmpbuf;
2023             }
2024             else if (ckWARN4_d(WARN_UTF8, WARN_SURROGATE, WARN_NON_UNICODE, WARN_NONCHAR)) {
2025                 (void) check_utf8_print((const U8*) tmps, len);
2026             }
2027         } /* else stream isn't utf8 */
2028         else if (DO_UTF8(sv)) { /* But if is utf8 internally, attempt to
2029                                    convert to bytes */
2030             STRLEN tmplen = len;
2031             bool utf8 = TRUE;
2032             U8 * const result = bytes_from_utf8((const U8*) tmps, &tmplen, &utf8);
2033             if (!utf8) {
2034
2035                 /* Here, succeeded in downgrading from utf8.  Set up to below
2036                  * output the converted value */
2037                 tmpbuf = result;
2038                 tmps = (char *) tmpbuf;
2039                 len = tmplen;
2040             }
2041             else {  /* Non-utf8 output stream, but string only representable in
2042                        utf8 */
2043                 assert((char *)result == tmps);
2044                 Perl_ck_warner_d(aTHX_ packWARN(WARN_UTF8),
2045                                  "Wide character in %s",
2046                                    PL_op ? OP_DESC(PL_op) : "print"
2047                                 );
2048                     /* Could also check that isn't one of the things to avoid
2049                      * in utf8 by using check_utf8_print(), but not doing so,
2050                      * since the stream isn't a UTF8 stream */
2051             }
2052         }
2053         /* To detect whether the process is about to overstep its
2054          * filesize limit we would need getrlimit().  We could then
2055          * also transparently raise the limit with setrlimit() --
2056          * but only until the system hard limit/the filesystem limit,
2057          * at which we would get EPERM.  Note that when using buffered
2058          * io the write failure can be delayed until the flush/close. --jhi */
2059         if (len && (PerlIO_write(fp,tmps,len) == 0))
2060             happy = FALSE;
2061         Safefree(tmpbuf);
2062         return happy ? !PerlIO_error(fp) : FALSE;
2063     }
2064 }
2065
2066 I32
2067 Perl_my_stat_flags(pTHX_ const U32 flags)
2068 {
2069     dSP;
2070     IO *io;
2071     GV* gv;
2072
2073     if (PL_op->op_flags & OPf_REF) {
2074         gv = cGVOP_gv;
2075       do_fstat:
2076         if (gv == PL_defgv) {
2077             if (PL_laststatval < 0)
2078                 SETERRNO(EBADF,RMS_IFI);
2079             return PL_laststatval;
2080         }
2081         io = GvIO(gv);
2082         do_fstat_have_io:
2083         PL_laststype = OP_STAT;
2084         PL_statgv = gv ? gv : (GV *)io;
2085         SvPVCLEAR(PL_statname);
2086         if (io) {
2087             if (IoIFP(io)) {
2088                 int fd = PerlIO_fileno(IoIFP(io));
2089                 if (fd < 0) {
2090                     /* E.g. PerlIO::scalar has no real fd. */
2091                     SETERRNO(EBADF,RMS_IFI);
2092                     return (PL_laststatval = -1);
2093                 } else {
2094                     return (PL_laststatval = PerlLIO_fstat(fd, &PL_statcache));
2095                 }
2096             } else if (IoDIRP(io)) {
2097                 return (PL_laststatval = PerlLIO_fstat(my_dirfd(IoDIRP(io)), &PL_statcache));
2098             }
2099         }
2100         PL_laststatval = -1;
2101         report_evil_fh(gv);
2102         SETERRNO(EBADF,RMS_IFI);
2103         return -1;
2104     }
2105     else if ((PL_op->op_private & (OPpFT_STACKED|OPpFT_AFTER_t))
2106              == OPpFT_STACKED)
2107         return PL_laststatval;
2108     else {
2109         SV* const sv = TOPs;
2110         const char *s, *d;
2111         STRLEN len;
2112         if ((gv = MAYBE_DEREF_GV_flags(sv,flags))) {
2113             goto do_fstat;
2114         }
2115         else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVIO) {
2116             io = MUTABLE_IO(SvRV(sv));
2117             gv = NULL;
2118             goto do_fstat_have_io;
2119         }
2120
2121         s = SvPV_flags_const(sv, len, flags);
2122         PL_statgv = NULL;
2123         sv_setpvn(PL_statname, s, len);
2124         d = SvPVX_const(PL_statname);           /* s now NUL-terminated */
2125         PL_laststype = OP_STAT;
2126         if (!IS_SAFE_PATHNAME(s, len, OP_NAME(PL_op))) {
2127             PL_laststatval = -1;
2128         }
2129         else {
2130             PL_laststatval = PerlLIO_stat(d, &PL_statcache);
2131         }
2132         if (PL_laststatval < 0 && ckWARN(WARN_NEWLINE) && should_warn_nl(s)) {
2133             GCC_DIAG_IGNORE_STMT(-Wformat-nonliteral); /* PL_warn_nl is constant */
2134             Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "stat");
2135             GCC_DIAG_RESTORE_STMT;
2136         }
2137         return PL_laststatval;
2138     }
2139 }
2140
2141
2142 I32
2143 Perl_my_lstat_flags(pTHX_ const U32 flags)
2144 {
2145     static const char* const no_prev_lstat = "The stat preceding -l _ wasn't an lstat";
2146     dSP;
2147     const char *file;
2148     STRLEN len;
2149     SV* const sv = TOPs;
2150     bool isio = FALSE;
2151     if (PL_op->op_flags & OPf_REF) {
2152         if (cGVOP_gv == PL_defgv) {
2153             if (PL_laststype != OP_LSTAT)
2154                 Perl_croak(aTHX_ "%s", no_prev_lstat);
2155             if (PL_laststatval < 0)
2156                 SETERRNO(EBADF,RMS_IFI);
2157             return PL_laststatval;
2158         }
2159         PL_laststatval = -1;
2160         if (ckWARN(WARN_IO)) {
2161             /* diag_listed_as: Use of -l on filehandle%s */
2162             Perl_warner(aTHX_ packWARN(WARN_IO),
2163                               "Use of -l on filehandle %" HEKf,
2164                               HEKfARG(GvENAME_HEK(cGVOP_gv)));
2165         }
2166         SETERRNO(EBADF,RMS_IFI);
2167         return -1;
2168     }
2169     if ((PL_op->op_private & (OPpFT_STACKED|OPpFT_AFTER_t))
2170              == OPpFT_STACKED) {
2171       if (PL_laststype != OP_LSTAT)
2172         Perl_croak(aTHX_ "%s", no_prev_lstat);
2173       return PL_laststatval;
2174     }
2175
2176     PL_laststype = OP_LSTAT;
2177     PL_statgv = NULL;
2178     if ( (  (SvROK(sv) && (  isGV_with_GP(SvRV(sv))
2179                           || (isio = SvTYPE(SvRV(sv)) == SVt_PVIO)  )
2180             )
2181          || isGV_with_GP(sv)
2182          )
2183       && ckWARN(WARN_IO)) {
2184         if (isio)
2185             /* diag_listed_as: Use of -l on filehandle%s */
2186             Perl_warner(aTHX_ packWARN(WARN_IO),
2187                              "Use of -l on filehandle");
2188         else
2189             /* diag_listed_as: Use of -l on filehandle%s */
2190             Perl_warner(aTHX_ packWARN(WARN_IO),
2191                              "Use of -l on filehandle %" HEKf,
2192                               HEKfARG(GvENAME_HEK((const GV *)
2193                                           (SvROK(sv) ? SvRV(sv) : sv))));
2194     }
2195     file = SvPV_flags_const(sv, len, flags);
2196     sv_setpv(PL_statname,file);
2197     if (!IS_SAFE_PATHNAME(file, len, OP_NAME(PL_op))) {
2198         PL_laststatval = -1;
2199     }
2200     else {
2201         PL_laststatval = PerlLIO_lstat(file,&PL_statcache);
2202     }
2203     if (PL_laststatval < 0 && ckWARN(WARN_NEWLINE) && should_warn_nl(file)) {
2204         GCC_DIAG_IGNORE_STMT(-Wformat-nonliteral); /* PL_warn_nl is constant */
2205         Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "lstat");
2206         GCC_DIAG_RESTORE_STMT;
2207     }
2208     return PL_laststatval;
2209 }
2210
2211 static void
2212 S_exec_failed(pTHX_ const char *cmd, int fd, int do_report)
2213 {
2214     const int e = errno;
2215     PERL_ARGS_ASSERT_EXEC_FAILED;
2216
2217     if (ckWARN(WARN_EXEC))
2218         Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't exec \"%s\": %s",
2219                     cmd, Strerror(e));
2220     if (do_report) {
2221         /* XXX silently ignore failures */
2222         PERL_UNUSED_RESULT(PerlLIO_write(fd, (void*)&e, sizeof(int)));
2223         PerlLIO_close(fd);
2224     }
2225 }
2226
2227 bool
2228 Perl_do_aexec5(pTHX_ SV *really, SV **mark, SV **sp,
2229                int fd, int do_report)
2230 {
2231     dVAR;
2232     PERL_ARGS_ASSERT_DO_AEXEC5;
2233 #if defined(__SYMBIAN32__) || defined(__LIBCATAMOUNT__)
2234     Perl_croak(aTHX_ "exec? I'm not *that* kind of operating system");
2235 #else
2236     assert(sp >= mark);
2237     ENTER;
2238     {
2239         const char **argv, **a;
2240         const char *tmps = NULL;
2241         Newx(argv, sp - mark + 1, const char*);
2242         SAVEFREEPV(argv);
2243         a = argv;
2244
2245         while (++mark <= sp) {
2246             if (*mark) {
2247                 char *arg = savepv(SvPV_nolen_const(*mark));
2248                 SAVEFREEPV(arg);
2249                 *a++ = arg;
2250             } else
2251                 *a++ = "";
2252         }
2253         *a = NULL;
2254         if (really) {
2255             tmps = savepv(SvPV_nolen_const(really));
2256             SAVEFREEPV(tmps);
2257         }
2258         if ((!really && argv[0] && *argv[0] != '/') ||
2259             (really && *tmps != '/'))           /* will execvp use PATH? */
2260             TAINT_ENV();                /* testing IFS here is overkill, probably */
2261         PERL_FPU_PRE_EXEC
2262         if (really && *tmps) {
2263             PerlProc_execvp(tmps,EXEC_ARGV_CAST(argv));
2264         } else if (argv[0]) {
2265             PerlProc_execvp(argv[0],EXEC_ARGV_CAST(argv));
2266         } else {
2267             SETERRNO(ENOENT,RMS_FNF);
2268         }
2269         PERL_FPU_POST_EXEC
2270         S_exec_failed(aTHX_ (really ? tmps : argv[0] ? argv[0] : ""), fd, do_report);
2271     }
2272     LEAVE;
2273 #endif
2274     return FALSE;
2275 }
2276
2277 #ifdef PERL_DEFAULT_DO_EXEC3_IMPLEMENTATION
2278
2279 bool
2280 Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report)
2281 {
2282     dVAR;
2283     const char **argv, **a;
2284     char *s;
2285     char *buf;
2286     char *cmd;
2287     /* Make a copy so we can change it */
2288     const Size_t cmdlen = strlen(incmd) + 1;
2289
2290     PERL_ARGS_ASSERT_DO_EXEC3;
2291
2292     ENTER;
2293     Newx(buf, cmdlen, char);
2294     SAVEFREEPV(buf);
2295     cmd = buf;
2296     memcpy(cmd, incmd, cmdlen);
2297
2298     while (*cmd && isSPACE(*cmd))
2299         cmd++;
2300
2301     /* save an extra exec if possible */
2302
2303 #ifdef CSH
2304     {
2305         char flags[PERL_FLAGS_MAX];
2306         if (strnEQ(cmd,PL_cshname,PL_cshlen) &&
2307             strBEGINs(cmd+PL_cshlen," -c")) {
2308           my_strlcpy(flags, "-c", PERL_FLAGS_MAX);
2309           s = cmd+PL_cshlen+3;
2310           if (*s == 'f') {
2311               s++;
2312               my_strlcat(flags, "f", PERL_FLAGS_MAX - 2);
2313           }
2314           if (*s == ' ')
2315               s++;
2316           if (*s++ == '\'') {
2317               char * const ncmd = s;
2318
2319               while (*s)
2320                   s++;
2321               if (s[-1] == '\n')
2322                   *--s = '\0';
2323               if (s[-1] == '\'') {
2324                   *--s = '\0';
2325                   PERL_FPU_PRE_EXEC
2326                   PerlProc_execl(PL_cshname, "csh", flags, ncmd, (char*)NULL);
2327                   PERL_FPU_POST_EXEC
2328                   *s = '\'';
2329                   S_exec_failed(aTHX_ PL_cshname, fd, do_report);
2330                   goto leave;
2331               }
2332           }
2333         }
2334     }
2335 #endif /* CSH */
2336
2337     /* see if there are shell metacharacters in it */
2338
2339     if (*cmd == '.' && isSPACE(cmd[1]))
2340         goto doshell;
2341
2342     if (strBEGINs(cmd,"exec") && isSPACE(cmd[4]))
2343         goto doshell;
2344
2345     s = cmd;
2346     while (isWORDCHAR(*s))
2347         s++;    /* catch VAR=val gizmo */
2348     if (*s == '=')
2349         goto doshell;
2350
2351     for (s = cmd; *s; s++) {
2352         if (*s != ' ' && !isALPHA(*s) &&
2353             strchr("$&*(){}[]'\";\\|?<>~`\n",*s)) {
2354             if (*s == '\n' && !s[1]) {
2355                 *s = '\0';
2356                 break;
2357             }
2358             /* handle the 2>&1 construct at the end */
2359             if (*s == '>' && s[1] == '&' && s[2] == '1'
2360                 && s > cmd + 1 && s[-1] == '2' && isSPACE(s[-2])
2361                 && (!s[3] || isSPACE(s[3])))
2362             {
2363                 const char *t = s + 3;
2364
2365                 while (*t && isSPACE(*t))
2366                     ++t;
2367                 if (!*t && (PerlLIO_dup2(1,2) != -1)) {
2368                     s[-2] = '\0';
2369                     break;
2370                 }
2371             }
2372           doshell:
2373             PERL_FPU_PRE_EXEC
2374             PerlProc_execl(PL_sh_path, "sh", "-c", cmd, (char *)NULL);
2375             PERL_FPU_POST_EXEC
2376             S_exec_failed(aTHX_ PL_sh_path, fd, do_report);
2377             goto leave;
2378         }
2379     }
2380
2381     Newx(argv, (s - cmd) / 2 + 2, const char*);
2382     SAVEFREEPV(argv);
2383     cmd = savepvn(cmd, s-cmd);
2384     SAVEFREEPV(cmd);
2385     a = argv;
2386     for (s = cmd; *s;) {
2387         while (isSPACE(*s))
2388             s++;
2389         if (*s)
2390             *(a++) = s;
2391         while (*s && !isSPACE(*s))
2392             s++;
2393         if (*s)
2394             *s++ = '\0';
2395     }
2396     *a = NULL;
2397     if (argv[0]) {
2398         PERL_FPU_PRE_EXEC
2399         PerlProc_execvp(argv[0],EXEC_ARGV_CAST(argv));
2400         PERL_FPU_POST_EXEC
2401         if (errno == ENOEXEC)           /* for system V NIH syndrome */
2402             goto doshell;
2403         S_exec_failed(aTHX_ argv[0], fd, do_report);
2404     }
2405 leave:
2406     LEAVE;
2407     return FALSE;
2408 }
2409
2410 #endif /* OS2 || WIN32 */
2411
2412 I32
2413 Perl_apply(pTHX_ I32 type, SV **mark, SV **sp)
2414 {
2415     I32 val;
2416     I32 tot = 0;
2417     const char *const what = PL_op_name[type];
2418     const char *s;
2419     STRLEN len;
2420     SV ** const oldmark = mark;
2421     bool killgp = FALSE;
2422
2423     PERL_ARGS_ASSERT_APPLY;
2424
2425     PERL_UNUSED_VAR(what); /* may not be used depending on compile options */
2426
2427     /* Doing this ahead of the switch statement preserves the old behaviour,
2428        where attempting to use kill as a taint test test would fail on
2429        platforms where kill was not defined.  */
2430 #ifndef HAS_KILL
2431     if (type == OP_KILL)
2432         Perl_die(aTHX_ PL_no_func, what);
2433 #endif
2434 #ifndef HAS_CHOWN
2435     if (type == OP_CHOWN)
2436         Perl_die(aTHX_ PL_no_func, what);
2437 #endif
2438
2439
2440 #define APPLY_TAINT_PROPER() \
2441     STMT_START {                                                        \
2442         if (TAINT_get) { TAINT_PROPER(what); }                          \
2443     } STMT_END
2444
2445     /* This is a first heuristic; it doesn't catch tainting magic. */
2446     if (TAINTING_get) {
2447         while (++mark <= sp) {
2448             if (SvTAINTED(*mark)) {
2449                 TAINT;
2450                 break;
2451             }
2452         }
2453         mark = oldmark;
2454     }
2455     switch (type) {
2456     case OP_CHMOD:
2457         APPLY_TAINT_PROPER();
2458         if (++mark <= sp) {
2459             val = SvIV(*mark);
2460             APPLY_TAINT_PROPER();
2461             tot = sp - mark;
2462             while (++mark <= sp) {
2463                 GV* gv;
2464                 if ((gv = MAYBE_DEREF_GV(*mark))) {
2465                     if (GvIO(gv) && IoIFP(GvIOp(gv))) {
2466 #ifdef HAS_FCHMOD
2467                         int fd = PerlIO_fileno(IoIFP(GvIOn(gv)));
2468                         APPLY_TAINT_PROPER();
2469                         if (fd < 0) {
2470                             SETERRNO(EBADF,RMS_IFI);
2471                             tot--;
2472                         } else if (fchmod(fd, val))
2473                             tot--;
2474 #else
2475                         Perl_die(aTHX_ PL_no_func, "fchmod");
2476 #endif
2477                     }
2478                     else {
2479                         SETERRNO(EBADF,RMS_IFI);
2480                         tot--;
2481                     }
2482                 }
2483                 else {
2484                     const char *name = SvPV_nomg_const(*mark, len);
2485                     APPLY_TAINT_PROPER();
2486                     if (!IS_SAFE_PATHNAME(name, len, "chmod") ||
2487                         PerlLIO_chmod(name, val)) {
2488                         tot--;
2489                     }
2490                 }
2491             }
2492         }
2493         break;
2494 #ifdef HAS_CHOWN
2495     case OP_CHOWN:
2496         APPLY_TAINT_PROPER();
2497         if (sp - mark > 2) {
2498             I32 val2;
2499             val = SvIVx(*++mark);
2500             val2 = SvIVx(*++mark);
2501             APPLY_TAINT_PROPER();
2502             tot = sp - mark;
2503             while (++mark <= sp) {
2504                 GV* gv;
2505                 if ((gv = MAYBE_DEREF_GV(*mark))) {
2506                     if (GvIO(gv) && IoIFP(GvIOp(gv))) {
2507 #ifdef HAS_FCHOWN
2508                         int fd = PerlIO_fileno(IoIFP(GvIOn(gv)));
2509                         APPLY_TAINT_PROPER();
2510                         if (fd < 0) {
2511                             SETERRNO(EBADF,RMS_IFI);
2512                             tot--;
2513                         } else if (fchown(fd, val, val2))
2514                             tot--;
2515 #else
2516                         Perl_die(aTHX_ PL_no_func, "fchown");
2517 #endif
2518                     }
2519                     else {
2520                         SETERRNO(EBADF,RMS_IFI);
2521                         tot--;
2522                     }
2523                 }
2524                 else {
2525                     const char *name = SvPV_nomg_const(*mark, len);
2526                     APPLY_TAINT_PROPER();
2527                     if (!IS_SAFE_PATHNAME(name, len, "chown") ||
2528                         PerlLIO_chown(name, val, val2)) {
2529                         tot--;
2530                     }
2531                 }
2532             }
2533         }
2534         break;
2535 #endif
2536 /*
2537 XXX Should we make lchown() directly available from perl?
2538 For now, we'll let Configure test for HAS_LCHOWN, but do
2539 nothing in the core.
2540     --AD  5/1998
2541 */
2542 #ifdef HAS_KILL
2543     case OP_KILL:
2544         APPLY_TAINT_PROPER();
2545         if (mark == sp)
2546             break;
2547         s = SvPVx_const(*++mark, len);
2548         if (*s == '-' && isALPHA(s[1]))
2549         {
2550             s++;
2551             len--;
2552             killgp = TRUE;
2553         }
2554         if (isALPHA(*s)) {
2555             if (*s == 'S' && s[1] == 'I' && s[2] == 'G') {
2556                 s += 3;
2557                 len -= 3;
2558             }
2559            if ((val = whichsig_pvn(s, len)) < 0)
2560                Perl_croak(aTHX_ "Unrecognized signal name \"%" SVf "\"",
2561                                 SVfARG(*mark));
2562         }
2563         else
2564         {
2565             val = SvIV(*mark);
2566             if (val < 0)
2567             {
2568                 killgp = TRUE;
2569                 val = -val;
2570             }
2571         }
2572         APPLY_TAINT_PROPER();
2573         tot = sp - mark;
2574
2575         while (++mark <= sp) {
2576             Pid_t proc;
2577             SvGETMAGIC(*mark);
2578             if (!(SvNIOK(*mark) || looks_like_number(*mark)))
2579                 Perl_croak(aTHX_ "Can't kill a non-numeric process ID");
2580             proc = SvIV_nomg(*mark);
2581             APPLY_TAINT_PROPER();
2582 #ifdef HAS_KILLPG
2583             /* use killpg in preference, as the killpg() wrapper for Win32
2584              * understands process groups, but the kill() wrapper doesn't */
2585             if (killgp ? PerlProc_killpg(proc, val)
2586                        : PerlProc_kill(proc, val))
2587 #else
2588             if (PerlProc_kill(killgp ? -proc: proc, val))
2589 #endif
2590                 tot--;
2591         }
2592         PERL_ASYNC_CHECK();
2593         break;
2594 #endif
2595     case OP_UNLINK:
2596         APPLY_TAINT_PROPER();
2597         tot = sp - mark;
2598         while (++mark <= sp) {
2599             s = SvPV_const(*mark, len);
2600             APPLY_TAINT_PROPER();
2601             if (!IS_SAFE_PATHNAME(s, len, "unlink")) {
2602                 tot--;
2603             }
2604             else if (PL_unsafe) {
2605                 if (UNLINK(s))
2606                 {
2607                     tot--;
2608                 }
2609 #if defined(__amigaos4__) && defined(NEWLIB)
2610                 else
2611                 {
2612                   /* Under AmigaOS4 unlink only 'fails' if the
2613                    * filename is invalid.  It may not remove the file
2614                    * if it's locked, so check if it's still around. */
2615                   if ((access(s,F_OK) != -1))
2616                   {
2617                     tot--;
2618                   }
2619                 }
2620 #endif
2621             }
2622             else {      /* don't let root wipe out directories without -U */
2623                 Stat_t statbuf;
2624                 if (PerlLIO_lstat(s, &statbuf) < 0)
2625                     tot--;
2626                 else if (S_ISDIR(statbuf.st_mode)) {
2627                     SETERRNO(EISDIR, SS_NOPRIV);
2628                     tot--;
2629                 }
2630                 else {
2631                     if (UNLINK(s))
2632                     {
2633                                 tot--;
2634                         }
2635 #if defined(__amigaos4__) && defined(NEWLIB)
2636                         else
2637                         {
2638                                 /* Under AmigaOS4 unlink only 'fails' if the filename is invalid */
2639                                 /* It may not remove the file if it's Locked, so check if it's still */
2640                                 /* arround */
2641                                 if((access(s,F_OK) != -1))
2642                                 {
2643                                         tot--;
2644                                 }
2645                         }       
2646 #endif
2647                 }
2648             }
2649         }
2650         break;
2651 #if defined(HAS_UTIME) || defined(HAS_FUTIMES)
2652     case OP_UTIME:
2653         APPLY_TAINT_PROPER();
2654         if (sp - mark > 2) {
2655 #if defined(HAS_FUTIMES)
2656             struct timeval utbuf[2];
2657             void *utbufp = utbuf;
2658 #elif defined(I_UTIME) || defined(VMS)
2659             struct utimbuf utbuf;
2660             struct utimbuf *utbufp = &utbuf;
2661 #else
2662             struct {
2663                 Time_t  actime;
2664                 Time_t  modtime;
2665             } utbuf;
2666             void *utbufp = &utbuf;
2667 #endif
2668
2669            SV* const accessed = *++mark;
2670            SV* const modified = *++mark;
2671
2672            /* Be like C, and if both times are undefined, let the C
2673             * library figure out what to do.  This usually means
2674             * "current time". */
2675
2676            if ( accessed == &PL_sv_undef && modified == &PL_sv_undef )
2677                 utbufp = NULL;
2678            else {
2679                 Zero(&utbuf, sizeof utbuf, char);
2680 #ifdef HAS_FUTIMES
2681                 utbuf[0].tv_sec = (long)SvIV(accessed);  /* time accessed */
2682                 utbuf[0].tv_usec = 0;
2683                 utbuf[1].tv_sec = (long)SvIV(modified);  /* time modified */
2684                 utbuf[1].tv_usec = 0;
2685 #elif defined(BIG_TIME)
2686                 utbuf.actime = (Time_t)SvNV(accessed);  /* time accessed */
2687                 utbuf.modtime = (Time_t)SvNV(modified); /* time modified */
2688 #else
2689                 utbuf.actime = (Time_t)SvIV(accessed);  /* time accessed */
2690                 utbuf.modtime = (Time_t)SvIV(modified); /* time modified */
2691 #endif
2692             }
2693             APPLY_TAINT_PROPER();
2694             tot = sp - mark;
2695             while (++mark <= sp) {
2696                 GV* gv;
2697                 if ((gv = MAYBE_DEREF_GV(*mark))) {
2698                     if (GvIO(gv) && IoIFP(GvIOp(gv))) {
2699 #ifdef HAS_FUTIMES
2700                         int fd =  PerlIO_fileno(IoIFP(GvIOn(gv)));
2701                         APPLY_TAINT_PROPER();
2702                         if (fd < 0) {
2703                             SETERRNO(EBADF,RMS_IFI);
2704                             tot--;
2705                         } else if (futimes(fd, (struct timeval *) utbufp))
2706                             tot--;
2707 #else
2708                         Perl_die(aTHX_ PL_no_func, "futimes");
2709 #endif
2710                     }
2711                     else {
2712                         tot--;
2713                     }
2714                 }
2715                 else {
2716                     const char * const name = SvPV_nomg_const(*mark, len);
2717                     APPLY_TAINT_PROPER();
2718                     if (!IS_SAFE_PATHNAME(name, len, "utime")) {
2719                         tot--;
2720                     }
2721                     else
2722 #ifdef HAS_FUTIMES
2723                     if (utimes(name, (struct timeval *)utbufp))
2724 #else
2725                     if (PerlLIO_utime(name, utbufp))
2726 #endif
2727                         tot--;
2728                 }
2729
2730             }
2731         }
2732         else
2733             tot = 0;
2734         break;
2735 #endif
2736     }
2737     return tot;
2738
2739 #undef APPLY_TAINT_PROPER
2740 }
2741
2742 /* Do the permissions in *statbufp allow some operation? */
2743 #ifndef VMS /* VMS' cando is in vms.c */
2744 bool
2745 Perl_cando(pTHX_ Mode_t mode, bool effective, const Stat_t *statbufp)
2746 /* effective is a flag, true for EUID, or for checking if the effective gid
2747  *  is in the list of groups returned from getgroups().
2748  */
2749 {
2750     PERL_ARGS_ASSERT_CANDO;
2751     PERL_UNUSED_CONTEXT;
2752
2753 #ifdef DOSISH
2754     /* [Comments and code from Len Reed]
2755      * MS-DOS "user" is similar to UNIX's "superuser," but can't write
2756      * to write-protected files.  The execute permission bit is set
2757      * by the Microsoft C library stat() function for the following:
2758      *          .exe files
2759      *          .com files
2760      *          .bat files
2761      *          directories
2762      * All files and directories are readable.
2763      * Directories and special files, e.g. "CON", cannot be
2764      * write-protected.
2765      * [Comment by Tom Dinger -- a directory can have the write-protect
2766      *          bit set in the file system, but DOS permits changes to
2767      *          the directory anyway.  In addition, all bets are off
2768      *          here for networked software, such as Novell and
2769      *          Sun's PC-NFS.]
2770      */
2771
2772      /* Atari stat() does pretty much the same thing. we set x_bit_set_in_stat
2773       * too so it will actually look into the files for magic numbers
2774       */
2775     return cBOOL(mode & statbufp->st_mode);
2776
2777 #else /* ! DOSISH */
2778 # ifdef __CYGWIN__
2779     if (ingroup(544,effective)) {     /* member of Administrators */
2780 # else
2781     if ((effective ? PerlProc_geteuid() : PerlProc_getuid()) == 0) {    /* root is special */
2782 # endif
2783         if (mode == S_IXUSR) {
2784             if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
2785                 return TRUE;
2786         }
2787         else
2788             return TRUE;                /* root reads and writes anything */
2789         return FALSE;
2790     }
2791     if (statbufp->st_uid == (effective ? PerlProc_geteuid() : PerlProc_getuid()) ) {
2792         if (statbufp->st_mode & mode)
2793             return TRUE;        /* ok as "user" */
2794     }
2795     else if (ingroup(statbufp->st_gid,effective)) {
2796         if (statbufp->st_mode & mode >> 3)
2797             return TRUE;        /* ok as "group" */
2798     }
2799     else if (statbufp->st_mode & mode >> 6)
2800         return TRUE;    /* ok as "other" */
2801     return FALSE;
2802 #endif /* ! DOSISH */
2803 }
2804 #endif /* ! VMS */
2805
2806 static bool
2807 S_ingroup(pTHX_ Gid_t testgid, bool effective)
2808 {
2809 #ifndef PERL_IMPLICIT_SYS
2810     /* PERL_IMPLICIT_SYS like Win32: getegid() etc. require the context. */
2811     PERL_UNUSED_CONTEXT;
2812 #endif
2813     if (testgid == (effective ? PerlProc_getegid() : PerlProc_getgid()))
2814         return TRUE;
2815 #ifdef HAS_GETGROUPS
2816     {
2817         Groups_t *gary = NULL;
2818         I32 anum;
2819         bool rc = FALSE;
2820
2821         anum = getgroups(0, gary);
2822         if (anum > 0) {
2823             Newx(gary, anum, Groups_t);
2824             anum = getgroups(anum, gary);
2825             while (--anum >= 0)
2826                 if (gary[anum] == testgid) {
2827                     rc = TRUE;
2828                     break;
2829                 }
2830
2831             Safefree(gary);
2832         }
2833         return rc;
2834     }
2835 #else
2836     return FALSE;
2837 #endif
2838 }
2839
2840 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
2841
2842 I32
2843 Perl_do_ipcget(pTHX_ I32 optype, SV **mark, SV **sp)
2844 {
2845     const key_t key = (key_t)SvNVx(*++mark);
2846     SV *nsv = optype == OP_MSGGET ? NULL : *++mark;
2847     const I32 flags = SvIVx(*++mark);
2848
2849     PERL_ARGS_ASSERT_DO_IPCGET;
2850     PERL_UNUSED_ARG(sp);
2851
2852     SETERRNO(0,0);
2853     switch (optype)
2854     {
2855 #ifdef HAS_MSG
2856     case OP_MSGGET:
2857         return msgget(key, flags);
2858 #endif
2859 #ifdef HAS_SEM
2860     case OP_SEMGET:
2861         return semget(key, (int) SvIV(nsv), flags);
2862 #endif
2863 #ifdef HAS_SHM
2864     case OP_SHMGET:
2865         return shmget(key, (size_t) SvUV(nsv), flags);
2866 #endif
2867 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
2868     default:
2869         /* diag_listed_as: msg%s not implemented */
2870         Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
2871 #endif
2872     }
2873     return -1;                  /* should never happen */
2874 }
2875
2876 I32
2877 Perl_do_ipcctl(pTHX_ I32 optype, SV **mark, SV **sp)
2878 {
2879     char *a;
2880     I32 ret = -1;
2881     const I32 id  = SvIVx(*++mark);
2882 #ifdef Semctl
2883     const I32 n   = (optype == OP_SEMCTL) ? SvIVx(*++mark) : 0;
2884 #endif
2885     const I32 cmd = SvIVx(*++mark);
2886     SV * const astr = *++mark;
2887     STRLEN infosize = 0;
2888     I32 getinfo = (cmd == IPC_STAT);
2889
2890     PERL_ARGS_ASSERT_DO_IPCCTL;
2891     PERL_UNUSED_ARG(sp);
2892
2893     switch (optype)
2894     {
2895 #ifdef HAS_MSG
2896     case OP_MSGCTL:
2897         if (cmd == IPC_STAT || cmd == IPC_SET)
2898             infosize = sizeof(struct msqid_ds);
2899         break;
2900 #endif
2901 #ifdef HAS_SHM
2902     case OP_SHMCTL:
2903         if (cmd == IPC_STAT || cmd == IPC_SET)
2904             infosize = sizeof(struct shmid_ds);
2905         break;
2906 #endif
2907 #ifdef HAS_SEM
2908     case OP_SEMCTL:
2909 #ifdef Semctl
2910         if (cmd == IPC_STAT || cmd == IPC_SET)
2911             infosize = sizeof(struct semid_ds);
2912         else if (cmd == GETALL || cmd == SETALL)
2913         {
2914             struct semid_ds semds;
2915             union semun semun;
2916 #ifdef EXTRA_F_IN_SEMUN_BUF
2917             semun.buff = &semds;
2918 #else
2919             semun.buf = &semds;
2920 #endif
2921             getinfo = (cmd == GETALL);
2922             if (Semctl(id, 0, IPC_STAT, semun) == -1)
2923                 return -1;
2924             infosize = semds.sem_nsems * sizeof(short);
2925                 /* "short" is technically wrong but much more portable
2926                    than guessing about u_?short(_t)? */
2927         }
2928 #else
2929         /* diag_listed_as: sem%s not implemented */
2930         Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
2931 #endif
2932         break;
2933 #endif
2934 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
2935     default:
2936         /* diag_listed_as: shm%s not implemented */
2937         Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
2938 #endif
2939     }
2940
2941     if (infosize)
2942     {
2943         if (getinfo)
2944         {
2945             SvPV_force_nolen(astr);
2946             a = SvGROW(astr, infosize+1);
2947         }
2948         else
2949         {
2950             STRLEN len;
2951             a = SvPV(astr, len);
2952             if (len != infosize)
2953                 Perl_croak(aTHX_ "Bad arg length for %s, is %lu, should be %ld",
2954                       PL_op_desc[optype],
2955                       (unsigned long)len,
2956                       (long)infosize);
2957         }
2958     }
2959     else
2960     {
2961         const IV i = SvIV(astr);
2962         a = INT2PTR(char *,i);          /* ouch */
2963     }
2964     SETERRNO(0,0);
2965     switch (optype)
2966     {
2967 #ifdef HAS_MSG
2968     case OP_MSGCTL:
2969         ret = msgctl(id, cmd, (struct msqid_ds *)a);
2970         break;
2971 #endif
2972 #ifdef HAS_SEM
2973     case OP_SEMCTL: {
2974 #ifdef Semctl
2975             union semun unsemds;
2976
2977             if(cmd == SETVAL) {
2978                 unsemds.val = PTR2nat(a);
2979             }
2980             else {
2981 #ifdef EXTRA_F_IN_SEMUN_BUF
2982                 unsemds.buff = (struct semid_ds *)a;
2983 #else
2984                 unsemds.buf = (struct semid_ds *)a;
2985 #endif
2986             }
2987             ret = Semctl(id, n, cmd, unsemds);
2988 #else
2989             /* diag_listed_as: sem%s not implemented */
2990             Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
2991 #endif
2992         }
2993         break;
2994 #endif
2995 #ifdef HAS_SHM
2996     case OP_SHMCTL:
2997         ret = shmctl(id, cmd, (struct shmid_ds *)a);
2998         break;
2999 #endif
3000     }
3001     if (getinfo && ret >= 0) {
3002         SvCUR_set(astr, infosize);
3003         *SvEND(astr) = '\0';
3004         SvSETMAGIC(astr);
3005     }
3006     return ret;
3007 }
3008
3009 I32
3010 Perl_do_msgsnd(pTHX_ SV **mark, SV **sp)
3011 {
3012 #ifdef HAS_MSG
3013     STRLEN len;
3014     const I32 id = SvIVx(*++mark);
3015     SV * const mstr = *++mark;
3016     const I32 flags = SvIVx(*++mark);
3017     const char * const mbuf = SvPV_const(mstr, len);
3018     const I32 msize = len - sizeof(long);
3019
3020     PERL_ARGS_ASSERT_DO_MSGSND;
3021     PERL_UNUSED_ARG(sp);
3022
3023     if (msize < 0)
3024         Perl_croak(aTHX_ "Arg too short for msgsnd");
3025     SETERRNO(0,0);
3026     if (id >= 0 && flags >= 0) {
3027       return msgsnd(id, (struct msgbuf *)mbuf, msize, flags);
3028     } else {
3029       SETERRNO(EINVAL,LIB_INVARG);
3030       return -1;
3031     }
3032 #else
3033     PERL_UNUSED_ARG(sp);
3034     PERL_UNUSED_ARG(mark);
3035     /* diag_listed_as: msg%s not implemented */
3036     Perl_croak(aTHX_ "msgsnd not implemented");
3037     return -1;
3038 #endif
3039 }
3040
3041 I32
3042 Perl_do_msgrcv(pTHX_ SV **mark, SV **sp)
3043 {
3044 #ifdef HAS_MSG
3045     char *mbuf;
3046     long mtype;
3047     I32 msize, flags, ret;
3048     const I32 id = SvIVx(*++mark);
3049     SV * const mstr = *++mark;
3050
3051     PERL_ARGS_ASSERT_DO_MSGRCV;
3052     PERL_UNUSED_ARG(sp);
3053
3054     /* suppress warning when reading into undef var --jhi */
3055     if (! SvOK(mstr))
3056         SvPVCLEAR(mstr);
3057     msize = SvIVx(*++mark);
3058     mtype = (long)SvIVx(*++mark);
3059     flags = SvIVx(*++mark);
3060     SvPV_force_nolen(mstr);
3061     mbuf = SvGROW(mstr, sizeof(long)+msize+1);
3062
3063     SETERRNO(0,0);
3064     if (id >= 0 && msize >= 0 && flags >= 0) {
3065         ret = msgrcv(id, (struct msgbuf *)mbuf, msize, mtype, flags);
3066     } else {
3067         SETERRNO(EINVAL,LIB_INVARG);
3068         ret = -1;
3069     }
3070     if (ret >= 0) {
3071         SvCUR_set(mstr, sizeof(long)+ret);
3072         *SvEND(mstr) = '\0';
3073         /* who knows who has been playing with this message? */
3074         SvTAINTED_on(mstr);
3075     }
3076     return ret;
3077 #else
3078     PERL_UNUSED_ARG(sp);
3079     PERL_UNUSED_ARG(mark);
3080     /* diag_listed_as: msg%s not implemented */
3081     Perl_croak(aTHX_ "msgrcv not implemented");
3082     return -1;
3083 #endif
3084 }
3085
3086 I32
3087 Perl_do_semop(pTHX_ SV **mark, SV **sp)
3088 {
3089 #ifdef HAS_SEM
3090     STRLEN opsize;
3091     const I32 id = SvIVx(*++mark);
3092     SV * const opstr = *++mark;
3093     const char * const opbuf = SvPV_const(opstr, opsize);
3094
3095     PERL_ARGS_ASSERT_DO_SEMOP;
3096     PERL_UNUSED_ARG(sp);
3097
3098     if (opsize < 3 * SHORTSIZE
3099         || (opsize % (3 * SHORTSIZE))) {
3100         SETERRNO(EINVAL,LIB_INVARG);
3101         return -1;
3102     }
3103     SETERRNO(0,0);
3104     /* We can't assume that sizeof(struct sembuf) == 3 * sizeof(short). */
3105     {
3106         const int nsops  = opsize / (3 * sizeof (short));
3107         int i      = nsops;
3108         short * const ops = (short *) opbuf;
3109         short *o   = ops;
3110         struct sembuf *temps, *t;
3111         I32 result;
3112
3113         Newx (temps, nsops, struct sembuf);
3114         t = temps;
3115         while (i--) {
3116             t->sem_num = *o++;
3117             t->sem_op  = *o++;
3118             t->sem_flg = *o++;
3119             t++;
3120         }
3121         result = semop(id, temps, nsops);
3122         Safefree(temps);
3123         return result;
3124     }
3125 #else
3126     /* diag_listed_as: sem%s not implemented */
3127     Perl_croak(aTHX_ "semop not implemented");
3128 #endif
3129 }
3130
3131 I32
3132 Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp)
3133 {
3134 #ifdef HAS_SHM
3135     char *shm;
3136     struct shmid_ds shmds;
3137     const I32 id = SvIVx(*++mark);
3138     SV * const mstr = *++mark;
3139     const I32 mpos = SvIVx(*++mark);
3140     const I32 msize = SvIVx(*++mark);
3141
3142     PERL_ARGS_ASSERT_DO_SHMIO;
3143     PERL_UNUSED_ARG(sp);
3144
3145     SETERRNO(0,0);
3146     if (shmctl(id, IPC_STAT, &shmds) == -1)
3147         return -1;
3148     if (mpos < 0 || msize < 0
3149         || (size_t)mpos + msize > (size_t)shmds.shm_segsz) {
3150         SETERRNO(EFAULT,SS_ACCVIO);             /* can't do as caller requested */
3151         return -1;
3152     }
3153     if (id >= 0) {
3154         shm = (char *)shmat(id, NULL, (optype == OP_SHMREAD) ? SHM_RDONLY : 0);
3155     } else {
3156         SETERRNO(EINVAL,LIB_INVARG);
3157         return -1;
3158     }
3159     if (shm == (char *)-1)      /* I hate System V IPC, I really do */
3160         return -1;
3161     if (optype == OP_SHMREAD) {
3162         char *mbuf;
3163         /* suppress warning when reading into undef var (tchrist 3/Mar/00) */
3164         SvGETMAGIC(mstr);
3165         SvUPGRADE(mstr, SVt_PV);
3166         if (! SvOK(mstr))
3167             SvPVCLEAR(mstr);
3168         SvPOK_only(mstr);
3169         mbuf = SvGROW(mstr, (STRLEN)msize+1);
3170
3171         Copy(shm + mpos, mbuf, msize, char);
3172         SvCUR_set(mstr, msize);
3173         *SvEND(mstr) = '\0';
3174         SvSETMAGIC(mstr);
3175         /* who knows who has been playing with this shared memory? */
3176         SvTAINTED_on(mstr);
3177     }
3178     else {
3179         STRLEN len;
3180
3181         const char *mbuf = SvPV_const(mstr, len);
3182         const I32 n = ((I32)len > msize) ? msize : (I32)len;
3183         Copy(mbuf, shm + mpos, n, char);
3184         if (n < msize)
3185             memzero(shm + mpos + n, msize - n);
3186     }
3187     return shmdt(shm);
3188 #else
3189     /* diag_listed_as: shm%s not implemented */
3190     Perl_croak(aTHX_ "shm I/O not implemented");
3191     return -1;
3192 #endif
3193 }
3194
3195 #endif /* SYSV IPC */
3196
3197 /*
3198 =head1 IO Functions
3199
3200 =for apidoc start_glob
3201
3202 Function called by C<do_readline> to spawn a glob (or do the glob inside
3203 perl on VMS).  This code used to be inline, but now perl uses C<File::Glob>
3204 this glob starter is only used by miniperl during the build process,
3205 or when PERL_EXTERNAL_GLOB is defined.
3206 Moving it away shrinks F<pp_hot.c>; shrinking F<pp_hot.c> helps speed perl up.
3207
3208 =cut
3209 */
3210
3211 PerlIO *
3212 Perl_start_glob (pTHX_ SV *tmpglob, IO *io)
3213 {
3214     SV * const tmpcmd = newSV(0);
3215     PerlIO *fp;
3216     STRLEN len;
3217     const char *s = SvPV(tmpglob, len);
3218
3219     PERL_ARGS_ASSERT_START_GLOB;
3220
3221     if (!IS_SAFE_SYSCALL(s, len, "pattern", "glob"))
3222         return NULL;
3223
3224     ENTER;
3225     SAVEFREESV(tmpcmd);
3226 #ifdef VMS /* expand the wildcards right here, rather than opening a pipe, */
3227            /* since spawning off a process is a real performance hit */
3228
3229 PerlIO * 
3230 Perl_vms_start_glob
3231    (pTHX_ SV *tmpglob,
3232     IO *io);
3233
3234     fp = Perl_vms_start_glob(aTHX_ tmpglob, io);
3235
3236 #else /* !VMS */
3237 # ifdef DOSISH
3238 #  if defined(OS2)
3239     sv_setpv(tmpcmd, "for a in ");
3240     sv_catsv(tmpcmd, tmpglob);
3241     sv_catpv(tmpcmd, "; do echo \"$a\\0\\c\"; done |");
3242 #  elif defined(DJGPP)
3243     sv_setpv(tmpcmd, "/dev/dosglob/"); /* File System Extension */
3244     sv_catsv(tmpcmd, tmpglob);
3245 #  else
3246     sv_setpv(tmpcmd, "perlglob ");
3247     sv_catsv(tmpcmd, tmpglob);
3248     sv_catpv(tmpcmd, " |");
3249 #  endif
3250 # elif defined(CSH)
3251     sv_setpvn(tmpcmd, PL_cshname, PL_cshlen);
3252     sv_catpv(tmpcmd, " -cf 'set nonomatch; glob ");
3253     sv_catsv(tmpcmd, tmpglob);
3254     sv_catpv(tmpcmd, "' 2>/dev/null |");
3255 # else
3256     sv_setpv(tmpcmd, "echo ");
3257     sv_catsv(tmpcmd, tmpglob);
3258     sv_catpv(tmpcmd, "|tr -s ' \t\f\r' '\\n\\n\\n\\n'|");
3259 # endif /* !DOSISH && !CSH */
3260     {
3261         SV ** const svp = hv_fetchs(GvHVn(PL_envgv), "LS_COLORS", 0);
3262         if (svp && *svp)
3263             save_helem_flags(GvHV(PL_envgv),
3264                              newSVpvs_flags("LS_COLORS", SVs_TEMP), svp,
3265                              SAVEf_SETMAGIC);
3266     }
3267     (void)do_open6(PL_last_in_gv, SvPVX_const(tmpcmd), SvCUR(tmpcmd),
3268                    NULL, NULL, 0);
3269     fp = IoIFP(io);
3270 #endif /* !VMS */
3271     LEAVE;
3272
3273     if (!fp && ckWARN(WARN_GLOB)) {
3274         Perl_warner(aTHX_ packWARN(WARN_GLOB), "glob failed (can't start child: %s)",
3275                     Strerror(errno));
3276     }
3277
3278     return fp;
3279 }
3280
3281 /*
3282  * ex: set ts=8 sts=4 sw=4 et:
3283  */