perl 3.0 patch #15 (combined patch)
[p5sagit/p5-mst-13.2.git] / doio.c
diff --git a/doio.c b/doio.c
index a2960ad..e19a6f2 100644 (file)
--- a/doio.c
+++ b/doio.c
@@ -1,4 +1,4 @@
-/* $Header: doio.c,v 3.0.1.2 89/11/11 04:25:51 lwall Locked $
+/* $Header: doio.c,v 3.0.1.7 90/03/14 12:26:24 lwall Locked $
  *
  *    Copyright (c) 1989, Larry Wall
  *
@@ -6,6 +6,28 @@
  *    as specified in the README file that comes with the perl 3.0 kit.
  *
  * $Log:       doio.c,v $
+ * Revision 3.0.1.7  90/03/14  12:26:24  lwall
+ * patch15: commands involving execs could cause malloc arena corruption
+ * 
+ * Revision 3.0.1.6  90/03/12  16:30:07  lwall
+ * patch13: system 'FOO=bar command' didn't invoke sh as it should
+ * 
+ * Revision 3.0.1.5  90/02/28  17:01:36  lwall
+ * patch9: open(FOO,"$filename\0") will now protect trailing spaces in filename
+ * patch9: removed obsolete checks to avoid opening block devices
+ * patch9: removed references to acusec and modusec that some utime.h's have
+ * patch9: added pipe function
+ * 
+ * Revision 3.0.1.4  89/12/21  19:55:10  lwall
+ * patch7: select now works on big-endian machines
+ * patch7: errno may now be a macro with an lvalue
+ * patch7: ANSI strerror() is now supported
+ * patch7: Configure now detects DG/UX thingies like [sg]etpgrp2 and utime.h
+ * 
+ * Revision 3.0.1.3  89/11/17  15:13:06  lwall
+ * patch5: some systems have symlink() but not lstat()
+ * patch5: some systems have dirent.h but not readdir()
+ * 
  * Revision 3.0.1.2  89/11/11  04:25:51  lwall
  * patch2: orthogonalized the file modes some so we can have <& +<& etc.
  * patch2: do_open() now detects sockets passed to process from parent
 #include <netdb.h>
 #endif
 
-#include <errno.h>
 #ifdef I_PWD
 #include <pwd.h>
 #endif
 #ifdef I_GRP
 #include <grp.h>
 #endif
-
-extern int errno;
+#ifdef I_UTIME
+#include <utime.h>
+#endif
 
 bool
-do_open(stab,name)
+do_open(stab,name,len)
 STAB *stab;
 register char *name;
+int len;
 {
     FILE *fp;
-    int len = strlen(name);
     register STIO *stio = stab_io(stab);
     char *myname = savestr(name);
     int result;
@@ -192,21 +214,6 @@ register char *name;
            return FALSE;
        }
        result = (statbuf.st_mode & S_IFMT);
-       if (result != S_IFREG &&
-#ifdef S_IFSOCK
-           result != S_IFSOCK &&
-#endif
-#ifdef S_IFFIFO
-           result != S_IFFIFO &&
-#endif
-#ifdef S_IFIFO
-           result != S_IFIFO &&
-#endif
-           result != 0 &&              /* socket? */
-           result != S_IFCHR) {
-           (void)fclose(fp);
-           return FALSE;
-       }
 #ifdef S_IFSOCK
        if (result == S_IFSOCK || result == 0)
            stio->type = 's';   /* in case a socket was passed in to us */
@@ -240,7 +247,7 @@ register STAB *stab;
        str_sset(stab_val(stab),str);
        STABSET(stab_val(stab));
        oldname = str_get(stab_val(stab));
-       if (do_open(stab,oldname)) {
+       if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
            if (inplace) {
 #ifdef TAINT
                taintproper("Insecure dependency in inplace open");
@@ -265,7 +272,7 @@ register STAB *stab;
                str_nset(str,">",1);
                str_cat(str,oldname);
                errno = 0;              /* in case sprintf set errno */
-               if (!do_open(argvoutstab,str->str_ptr))
+               if (!do_open(argvoutstab,str->str_ptr,str->str_cur))
                    fatal("Can't do inplace edit");
                defoutstab = argvoutstab;
 #ifdef FCHMOD
@@ -293,6 +300,49 @@ register STAB *stab;
     return Nullfp;
 }
 
+void
+do_pipe(str, rstab, wstab)
+STR *str;
+STAB *rstab;
+STAB *wstab;
+{
+    register STIO *rstio;
+    register STIO *wstio;
+    int fd[2];
+
+    if (!rstab)
+       goto badexit;
+    if (!wstab)
+       goto badexit;
+
+    rstio = stab_io(rstab);
+    wstio = stab_io(wstab);
+
+    if (!rstio)
+       rstio = stab_io(rstab) = stio_new();
+    else if (rstio->ifp)
+       do_close(rstab,FALSE);
+    if (!wstio)
+       wstio = stab_io(wstab) = stio_new();
+    else if (wstio->ifp)
+       do_close(wstab,FALSE);
+
+    if (pipe(fd) < 0)
+       goto badexit;
+    rstio->ifp = fdopen(fd[0], "r");
+    wstio->ofp = fdopen(fd[1], "w");
+    wstio->ifp = wstio->ofp;
+    rstio->type = '<';
+    wstio->type = '>';
+
+    str_sset(str,&str_yes);
+    return;
+
+badexit:
+    str_sset(str,&str_undef);
+    return;
+}
+
 bool
 do_close(stab,explicit)
 STAB *stab;
@@ -510,7 +560,7 @@ int *arglast;
     else {
        str_sset(statname,ary->ary_array[sp]);
        statstab = Nullstab;
-#ifdef SYMLINK
+#ifdef LSTAT
        if (arg->arg_type == O_LSTAT)
            i = lstat(str_get(statname),&statcache);
        else
@@ -884,6 +934,9 @@ char *cmd;
 
     /* see if there are shell metacharacters in it */
 
+    for (s = cmd; *s && isalpha(*s); s++) ;    /* catch VAR=val gizmo */
+    if (*s == '=')
+       goto doshell;
     for (s = cmd; *s; s++) {
        if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
            if (*s == '\n' && !s[1]) {
@@ -1471,20 +1524,52 @@ int *arglast;
     int nfound;
     struct timeval timebuf;
     struct timeval *tbuf = &timebuf;
+    int growsize;
+#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
+    int masksize;
+    int offset;
+    char *fd_sets[4];
+    int k;
+
+#if BYTEORDER & 0xf0000
+#define ORDERBYTE (0x88888888 - BYTEORDER)
+#else
+#define ORDERBYTE (0x4444 - BYTEORDER)
+#endif
+
+#endif
 
     for (i = 1; i <= 3; i++) {
-       j = st[sp+i]->str_len;
+       j = st[sp+i]->str_cur;
        if (maxlen < j)
            maxlen = j;
     }
+
+#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
+    growsize = maxlen;         /* little endians can use vecs directly */
+#else
+#ifdef NFDBITS
+
+#ifndef NBBY
+#define NBBY 8
+#endif
+
+    masksize = NFDBITS / NBBY;
+#else
+    masksize = sizeof(long);   /* documented int, everyone seems to use long */
+#endif
+    growsize = maxlen + (masksize - (maxlen % masksize));
+    Zero(&fd_sets[0], 4, char*);
+#endif
+
     for (i = 1; i <= 3; i++) {
        str = st[sp+i];
        j = str->str_len;
-       if (j < maxlen) {
+       if (j < growsize) {
            if (str->str_pok) {
-               str_grow(str,maxlen);
+               str_grow(str,growsize);
                s = str_get(str) + j;
-               while (++j <= maxlen) {
+               while (++j <= growsize) {
                    *s++ = '\0';
                }
            }
@@ -1493,6 +1578,16 @@ int *arglast;
                str->str_ptr = Nullch;
            }
        }
+#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
+       s = str->str_ptr;
+       if (s) {
+           New(403, fd_sets[i], growsize, char);
+           for (offset = 0; offset < growsize; offset += masksize) {
+               for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
+                   fd_sets[i][j+offset] = s[(k % masksize) + offset];
+           }
+       }
+#endif
     }
     str = st[sp+4];
     if (str->str_nok || str->str_pok) {
@@ -1506,12 +1601,31 @@ int *arglast;
     else
        tbuf = Null(struct timeval*);
 
+#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
     nfound = select(
        maxlen * 8,
        st[sp+1]->str_ptr,
        st[sp+2]->str_ptr,
        st[sp+3]->str_ptr,
        tbuf);
+#else
+    nfound = select(
+       maxlen * 8,
+       fd_sets[1],
+       fd_sets[2],
+       fd_sets[3],
+       tbuf);
+    for (i = 1; i <= 3; i++) {
+       if (fd_sets[i]) {
+           str = st[sp+i];
+           s = str->str_ptr;
+           for (offset = 0; offset < growsize; offset += masksize) {
+               for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
+                   s[(k % masksize) + offset] = fd_sets[i][j+offset];
+           }
+       }
+    }
+#endif
 
     st[++sp] = str_static(&str_no);
     str_numset(st[sp], (double)nfound);
@@ -1717,7 +1831,7 @@ STAB *stab;
 int gimme;
 int *arglast;
 {
-#ifdef DIRENT
+#if defined(DIRENT) && defined(READDIR)
     register ARRAY *ary = stack;
     register STR **st = ary->ary_array;
     register int sp = arglast[1];
@@ -1892,7 +2006,7 @@ int *arglast;
                    tot--;
            }
            else {      /* don't let root wipe out directories without -U */
-#ifdef SYMLINK
+#ifdef LSTAT
                if (lstat(s,&statbuf) < 0 ||
 #else
                if (stat(s,&statbuf) < 0 ||
@@ -1911,13 +2025,18 @@ int *arglast;
        taintproper("Insecure dependency in utime");
 #endif
        if (items > 2) {
+#ifdef I_UTIME
+           struct utimbuf utbuf;
+#else
            struct {
-               long    atime,
-                       mtime;
+               long    actime;
+               long    modtime;
            } utbuf;
+#endif
 
-           utbuf.atime = (long)str_gnum(st[++sp]);    /* time accessed */
-           utbuf.mtime = (long)str_gnum(st[++sp]);    /* time modified */
+           Zero(&utbuf, sizeof utbuf, char);
+           utbuf.actime = (long)str_gnum(st[++sp]);    /* time accessed */
+           utbuf.modtime = (long)str_gnum(st[++sp]);    /* time modified */
            items -= 2;
 #ifndef lint
            tot = items;