BSD 4_4 release
[unix-history] / usr / src / usr.bin / ex / ex_io.c
index be791ab..d38a673 100644 (file)
@@ -1,10 +1,24 @@
-/* Copyright (c) 1981 Regents of the University of California */
-static char *sccsid = "@(#)ex_io.c     7.3     %G%";
+/*-
+ * Copyright (c) 1980, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This module is believed to contain source code proprietary to AT&T.
+ * Use and redistribution is subject to the Berkeley Software License
+ * Agreement and your Software Agreement with AT&T (Western Electric).
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)ex_io.c    8.1 (Berkeley) 6/9/93";
+#endif /* not lint */
+
 #include "ex.h"
 #include "ex_argv.h"
 #include "ex_temp.h"
 #include "ex_tty.h"
 #include "ex_vis.h"
 #include "ex.h"
 #include "ex_argv.h"
 #include "ex_temp.h"
 #include "ex_tty.h"
 #include "ex_vis.h"
+#include <sys/file.h>
+#include <sys/exec.h>
+#include "pathnames.h"
 
 /*
  * File input/output, source, preserve and recover
 
 /*
  * File input/output, source, preserve and recover
@@ -28,6 +42,17 @@ int  cntln;
 long   cntnull;                /* Count of nulls " */
 long   cntodd;                 /* Count of non-ascii characters " */
 
 long   cntnull;                /* Count of nulls " */
 long   cntodd;                 /* Count of non-ascii characters " */
 
+#ifdef FLOCKFILE
+/*
+ * The alternate, saved and current file are locked the extent of the
+ * time that they are active. If the saved file is exchanged
+ * with the alternate file, the file descriptors are exchanged
+ * and the lock is not released.
+ */
+int    io_savedfile, io_altfile, io_curr ;
+int    lock_savedfile, lock_altfile, lock_curr ;
+#endif FLOCKFILE
+
 /*
  * Parse file name for command encoded by comm.
  * If comm is E then command is doomed and we are
 /*
  * Parse file name for command encoded by comm.
  * If comm is E then command is doomed and we are
@@ -38,12 +63,22 @@ filename(comm)
 {
        register int c = comm, d;
        register int i;
 {
        register int c = comm, d;
        register int i;
+#ifdef FLOCKFILE
+       int lock ;
 
 
-       d = getchar();
+       lock = 0 ;
+#endif FLOCKFILE
+
+       d = ex_getchar();
        if (endcmd(d)) {
                if (savedfile[0] == 0 && comm != 'f')
                        error("No file|No current filename");
                CP(file, savedfile);
        if (endcmd(d)) {
                if (savedfile[0] == 0 && comm != 'f')
                        error("No file|No current filename");
                CP(file, savedfile);
+#ifdef FLOCKFILE
+               if (io_curr && io_curr != io_savedfile) close(io_curr) ;
+               lock = lock_curr = lock_savedfile ;
+               io_curr = io_savedfile ;
+#endif FLOCKFILE
                wasalt = (isalt > 0) ? isalt-1 : 0;
                isalt = 0;
                oldadot = altdot;
                wasalt = (isalt > 0) ? isalt-1 : 0;
                isalt = 0;
                oldadot = altdot;
@@ -69,17 +104,41 @@ filename(comm)
 
                case 'e':
                        if (savedfile[0]) {
 
                case 'e':
                        if (savedfile[0]) {
+#ifdef FLOCKFILE
+                               if (strcmp(file,savedfile) == 0) break ;
+#endif FLOCKFILE
                                altdot = lineDOT();
                                CP(altfile, savedfile);
                                altdot = lineDOT();
                                CP(altfile, savedfile);
+#ifdef FLOCKFILE
+                               if (io_altfile) close (io_altfile) ;
+                               io_altfile = io_savedfile ;
+                               lock_altfile = lock_savedfile ;
+                               io_savedfile = 0 ;
+#endif FLOCKFILE
                        }
                        CP(savedfile, file);
                        }
                        CP(savedfile, file);
+#ifdef FLOCKFILE
+                       io_savedfile = io_curr ;
+                       lock_savedfile = lock_curr ;
+                       io_curr = 0 ;           lock = lock_curr = 0 ;
+#endif FLOCKFILE
                        break;
 
                default:
                        if (file[0]) {
                        break;
 
                default:
                        if (file[0]) {
+#ifdef FLOCKFILE
+                               if (wasalt) break ;
+#endif
                                if (c != 'E')
                                        altdot = lineDOT();
                                CP(altfile, file);
                                if (c != 'E')
                                        altdot = lineDOT();
                                CP(altfile, file);
+#ifdef FLOCKFILE
+                               if (io_altfile
+                               && io_altfile != io_curr) close (io_altfile) ;
+                               io_altfile = io_curr ;
+                               lock_altfile = lock_curr ;
+                               io_curr = 0 ;           lock = lock_curr = 0 ;
+#endif FLOCKFILE
                        }
                        break;
                }
                        }
                        break;
                }
@@ -90,19 +149,25 @@ filename(comm)
                lprintf("\"%s\"", file);
                if (comm == 'f') {
                        if (value(READONLY))
                lprintf("\"%s\"", file);
                if (comm == 'f') {
                        if (value(READONLY))
-                               printf(" [Read only]");
+                               ex_printf(" [Read only]");
                        if (!edited)
                        if (!edited)
-                               printf(" [Not edited]");
+                               ex_printf(" [Not edited]");
                        if (tchng)
                        if (tchng)
-                               printf(" [Modified]");
+                               ex_printf(" [Modified]");
+#ifdef FLOCKFILE
+                       if (lock == LOCK_SH)
+                               ex_printf(" [Shared lock]") ;
+                       else if (lock == LOCK_EX)
+                               ex_printf(" [Exclusive lock]") ;
+#endif FLOCKFILE
                }
                flush();
        } else
                }
                flush();
        } else
-               printf("No file ");
+               ex_printf("No file ");
        if (comm == 'f') {
                if (!(i = lineDOL()))
                        i++;
        if (comm == 'f') {
                if (!(i = lineDOL()))
                        i++;
-               printf(" line %d of %d --%ld%%--", lineDOT(), lineDOL(),
+               ex_printf(" line %d of %d --%ld%%--", lineDOT(), lineDOL(),
                    (long) 100 * lineDOT() / i);
        }
 }
                    (long) 100 * lineDOT() / i);
        }
 }
@@ -120,11 +185,11 @@ getargs()
        pastwh();
        if (peekchar() == '+') {
                for (cp = fpatbuf;;) {
        pastwh();
        if (peekchar() == '+') {
                for (cp = fpatbuf;;) {
-                       c = *cp++ = getchar();
+                       c = *cp++ = ex_getchar();
                        if (cp >= &fpatbuf[sizeof(fpatbuf)])
                                error("Pattern too long");
                        if (c == '\\' && isspace(peekchar()))
                        if (cp >= &fpatbuf[sizeof(fpatbuf)])
                                error("Pattern too long");
                        if (c == '\\' && isspace(peekchar()))
-                               c = getchar();
+                               c = ex_getchar();
                        if (c == EOF || isspace(c)) {
                                ungetchar(c);
                                *--cp = 0;
                        if (c == EOF || isspace(c)) {
                                ungetchar(c);
                                *--cp = 0;
@@ -137,7 +202,7 @@ getargs()
                return (0);
        CP(genbuf, "echo "); cp = &genbuf[5];
        for (;;) {
                return (0);
        CP(genbuf, "echo "); cp = &genbuf[5];
        for (;;) {
-               c = getchar();
+               c = ex_getchar();
                if (endcmd(c)) {
                        ungetchar(c);
                        break;
                if (endcmd(c)) {
                        ungetchar(c);
                        break;
@@ -146,7 +211,7 @@ getargs()
 
                case '\\':
                        if (any(peekchar(), "#%|"))
 
                case '\\':
                        if (any(peekchar(), "#%|"))
-                               c = getchar();
+                               c = ex_getchar();
                        /* fall into... */
 
                default:
                        /* fall into... */
 
                default:
@@ -213,7 +278,7 @@ glob(gp)
        }
        if (pipe(pvec) < 0)
                error("Can't make pipe to glob");
        }
        if (pipe(pvec) < 0)
                error("Can't make pipe to glob");
-       pid = fork();
+       pid = vfork();
        io = pvec[0];
        if (pid < 0) {
                close(pvec[1]);
        io = pvec[0];
        if (pid < 0) {
                close(pvec[1]);
@@ -222,13 +287,21 @@ glob(gp)
        if (pid == 0) {
                int oerrno;
 
        if (pid == 0) {
                int oerrno;
 
+               if (genbuf) {
+                       register char *ccp = genbuf;
+                       while (*ccp)
+                               *ccp++ &= TRIM;
+               }
                close(1);
                dup(pvec[1]);
                close(pvec[0]);
                close(2);       /* so errors don't mess up the screen */
                close(1);
                dup(pvec[1]);
                close(pvec[0]);
                close(2);       /* so errors don't mess up the screen */
-               open("/dev/null", 1);
+               ignore(open(_PATH_DEVNULL, 1));
                execl(svalue(SHELL), "sh", "-c", genbuf, 0);
                execl(svalue(SHELL), "sh", "-c", genbuf, 0);
-               oerrno = errno; close(1); dup(2); errno = oerrno;
+               oerrno = errno;
+               close(1);
+               dup(2);
+               errno = oerrno;
                filioerr(svalue(SHELL));
        }
        close(pvec[1]);
                filioerr(svalue(SHELL));
        }
        close(pvec[1]);
@@ -266,11 +339,13 @@ glob(gp)
  */
 gscan()
 {
  */
 gscan()
 {
+#ifndef        vms                     /* Never have meta-characters in vms */
        register char *cp;
 
        for (cp = genbuf; *cp; cp++)
                if (any(*cp, "~{[*?$`'\"\\"))
                        return (1);
        register char *cp;
 
        for (cp = genbuf; *cp; cp++)
                if (any(*cp, "~{[*?$`'\"\\"))
                        return (1);
+#endif
        return (0);
 }
 
        return (0);
 }
 
@@ -290,7 +365,6 @@ getone()
        str = G.argv[G.argc0 - 1];
        if (strlen(str) > FNSIZE - 4)
                error("Filename too long");
        str = G.argv[G.argc0 - 1];
        if (strlen(str) > FNSIZE - 4)
                error("Filename too long");
-samef:
        CP(file, str);
 }
 
        CP(file, str);
 }
 
@@ -303,9 +377,12 @@ rop(c)
 {
        register int i;
        struct stat stbuf;
 {
        register int i;
        struct stat stbuf;
-       short magic;
+       struct exec head;
        static int ovro;        /* old value(READONLY) */
        static int denied;      /* 1 if READONLY was set due to file permissions */
        static int ovro;        /* old value(READONLY) */
        static int denied;      /* 1 if READONLY was set due to file permissions */
+#ifdef FLOCKFILE
+       int *lp, *iop;
+#endif FLOCKFILE
 
        io = open(file, 0);
        if (io < 0) {
 
        io = open(file, 0);
        if (io < 0) {
@@ -317,7 +394,7 @@ rop(c)
                         * this is ugly, and it screws up the + option.
                         */
                        if (!seenprompt) {
                         * this is ugly, and it screws up the + option.
                         */
                        if (!seenprompt) {
-                               printf(" [New file]");
+                               ex_printf(" [New file]");
                                noonl();
                                return;
                        }
                                noonl();
                                return;
                        }
@@ -334,7 +411,7 @@ rop(c)
        case S_IFCHR:
                if (isatty(io))
                        error(" Teletype");
        case S_IFCHR:
                if (isatty(io))
                        error(" Teletype");
-               if (samei(&stbuf, "/dev/null"))
+               if (samei(&stbuf, _PATH_DEVNULL))
                        break;
                error(" Character special file");
 
                        break;
                error(" Character special file");
 
@@ -346,17 +423,18 @@ rop(c)
                if (xflag)
                        break;
 #endif
                if (xflag)
                        break;
 #endif
-               i = read(io, (char *) &magic, sizeof(magic));
-               lseek(io, 0l, 0);
-               if (i != sizeof(magic))
+               i = read(io, (char *)&head, sizeof(head));
+               (void)lseek(io, 0L, L_SET);
+               if (i != sizeof(head))
                        break;
                        break;
-               switch (magic) {
+#ifndef vms
+               switch ((int)head.a_magic) {
 
                case 0405:      /* data overlay on exec */
 
                case 0405:      /* data overlay on exec */
-               case 0407:      /* unshared */
-               case 0410:      /* shared text */
+               case OMAGIC:    /* unshared */
+               case NMAGIC:    /* shared text */
                case 0411:      /* separate I/D */
                case 0411:      /* separate I/D */
-               case 0413:      /* VM/Unix demand paged */
+               case ZMAGIC:    /* VM/Unix demand paged */
                case 0430:      /* PDP-11 Overlay shared */
                case 0431:      /* PDP-11 Overlay sep I/D */
                        error(" Executable");
                case 0430:      /* PDP-11 Overlay shared */
                case 0431:      /* PDP-11 Overlay sep I/D */
                        error(" Executable");
@@ -372,18 +450,24 @@ rop(c)
                case 0177545:
                case 0177555:
                        error(" Archive");
                case 0177545:
                case 0177555:
                        error(" Archive");
+               case 070707:
+                       error(" Cpio file");
 
                default:
 
                default:
-#ifdef mbb
-                       /* C/70 has a 10 bit byte */
-                       if (magic & 03401600)
-#else
-                       /* Everybody else has an 8 bit byte */
-                       if (magic & 0100200)
+                       {
+                               char *bp = (char *)&head;
+                               if ((u_char)bp[0] == (u_char)'\037' &&
+                                   (u_char)bp[1] == (u_char)'\235')
+                                       error(" Compressed file");
+#ifdef ARCHIVES_ARE_OK
+                               if (!strncmp(bp, "!<arch>\n__.SYMDEF", 17)
+                                   || !strncmp(bp, "!<arch>\n", 8))
+                                       error(" Archive");
 #endif
 #endif
-                               error(" Non-ascii file");
+                       }
                        break;
                }
                        break;
                }
+#endif
        }
        if (c != 'r') {
                if (value(READONLY) && denied) {
        }
        if (c != 'r') {
                if (value(READONLY) && denied) {
@@ -397,9 +481,56 @@ rop(c)
                }
        }
        if (value(READONLY)) {
                }
        }
        if (value(READONLY)) {
-               printf(" [Read only]");
+               ex_printf(" [Read only]");
                flush();
        }
                flush();
        }
+#ifdef FLOCKFILE
+       /*
+        * Attempt to lock the file. We use an sharable lock if reading
+        * the file, and an exclusive lock if editting a file.
+        * The lock will be released when the file is no longer being
+        * referenced. At any time, the editor can have as many as
+        * three files locked, and with different lock statuses.
+        */
+       /*
+        * if this is either the saved or alternate file or current file,
+        * point to the appropriate descriptor and file lock status.
+        */
+       if (strcmp (file,savedfile) == 0) {
+               if (!io_savedfile) io_savedfile = dup(io) ;
+               lp = &lock_savedfile ;  iop = &io_savedfile ;
+       } else if (strcmp (file,altfile) == 0) {
+               if (!io_altfile) io_altfile = dup(io) ;
+               lp = &lock_altfile ;    iop = &io_altfile ;
+       } else {
+               /* throw away current lock, accquire new current lock */
+               if (io_curr) close (io_curr) ;
+               io_curr = dup(io) ;
+               lp = &lock_curr ;       iop = &io_curr ;
+               lock_curr = 0 ;
+       }
+       if (c == 'r' || value(READONLY) || *lp == 0) {
+               /* if we have a lock already, don't bother */
+               if (!*lp) {
+                       /* try for a shared lock */
+                       if (flock(*iop, LOCK_SH|LOCK_NB) < 0
+                       && errno == EWOULDBLOCK) {
+                               ex_printf (
+                       " [FILE BEING MODIFIED BY ANOTHER PROCESS]") ;
+                               flush();
+                               goto fail_lock ;
+                       } else *lp = LOCK_SH ;
+               }
+       }
+       if ( c != 'r'  && !value(READONLY) && *lp != LOCK_EX) {
+               /* if we are editting the file, upgrade to an exclusive lock. */
+               if (flock(*iop, LOCK_EX|LOCK_NB) < 0 && errno == EWOULDBLOCK) {
+                       ex_printf (" [File open by another process]") ;
+                       flush();
+               } else *lp = LOCK_EX ;
+       }
+fail_lock:
+#endif FLOCKFILE
        if (c == 'r')
                setdot();
        else
        if (c == 'r')
                setdot();
        else
@@ -413,17 +544,32 @@ rop(c)
 rop2()
 {
        line *first, *last, *a;
 rop2()
 {
        line *first, *last, *a;
+       struct stat statb;
 
        deletenone();
        clrstats();
        first = addr2 + 1;
 
        deletenone();
        clrstats();
        first = addr2 + 1;
+       if (fstat(io, &statb) < 0)
+               bsize = LBSIZE;
+       else {
+               bsize = statb.st_blksize;
+               if (bsize <= 0)
+                       bsize = LBSIZE;
+       }
        ignore(append(getfile, addr2));
        last = dot;
        ignore(append(getfile, addr2));
        last = dot;
-       for (a=first; a<=last; a++) {
-               if (a==first+5 && last-first > 10)
-                       a = last - 4;
-               getline(*a);
-               checkmodeline(linebuf);
+       /*
+        *      if the modeline variable is set,
+        *      check the first and last five lines of the file
+        *      for a mode line.
+        */
+       if (value(MODELINE)) {
+               for (a=first; a<=last; a++) {
+                       if (a==first+5 && last-first > 10)
+                               a = last - 4;
+                       getline(*a);
+                       checkmodeline(linebuf);
+               }
        }
 }
 
        }
 }
 
@@ -463,13 +609,6 @@ other:
                        vreplace(0, LINES, lineDOL());
                }
        }
                        vreplace(0, LINES, lineDOL());
                }
        }
-       if (laste) {
-#ifdef VMUNIX
-               tlaste();
-#endif
-               laste = 0;
-               sync();
-       }
 }
 
 /*
 }
 
 /*
@@ -500,6 +639,9 @@ bool dofname;       /* if 1 call filename, else use savedfile */
        register int c, exclam, nonexist;
        line *saddr1, *saddr2;
        struct stat stbuf;
        register int c, exclam, nonexist;
        line *saddr1, *saddr2;
        struct stat stbuf;
+#ifdef FLOCKFILE
+       int *lp, *iop ;
+#endif FLOCKFILE
 
        c = 0;
        exclam = 0;
 
        c = 0;
        exclam = 0;
@@ -527,6 +669,23 @@ bool dofname;      /* if 1 call filename, else use savedfile */
                lprintf("\"%s\"", file);
        }
        nonexist = stat(file, &stbuf);
                lprintf("\"%s\"", file);
        }
        nonexist = stat(file, &stbuf);
+#ifdef FLOCKFILE
+       /*
+        * if this is either the saved or alternate file or current file,
+        * point to the appropriate descriptor and file lock status.
+        */
+       if (strcmp (file,savedfile) == 0) {
+               lp = &lock_savedfile ;  iop = &io_savedfile ;
+       } else if (strcmp (file,altfile) == 0) {
+               lp = &lock_altfile ;    iop = &io_altfile ;
+       } else {
+               lp = &lock_curr ;       iop = &io_curr ;
+       }
+       if (!*iop && !nonexist){
+               *lp = 0 ;
+               if ((*iop = open(file, 1)) < 0) *iop = 0 ;
+       }
+#endif FLOCKFILE
        switch (c) {
 
        case 0:
        switch (c) {
 
        case 0:
@@ -537,9 +696,9 @@ bool dofname;       /* if 1 call filename, else use savedfile */
                        if (nonexist)
                                break;
                        if ((stbuf.st_mode & S_IFMT) == S_IFCHR) {
                        if (nonexist)
                                break;
                        if ((stbuf.st_mode & S_IFMT) == S_IFCHR) {
-                               if (samei(&stbuf, "/dev/null"))
+                               if (samei(&stbuf, _PATH_DEVNULL))
                                        break;
                                        break;
-                               if (samei(&stbuf, "/dev/tty"))
+                               if (samei(&stbuf, _PATH_TTY))
                                        break;
                        }
                        io = open(file, 1);
                                        break;
                        }
                        io = open(file, 1);
@@ -564,19 +723,38 @@ cre:
 /*
                synctmp();
 */
 /*
                synctmp();
 */
+#ifdef FLOCKFILE
+       if (*iop && !*lp != LOCK_EX && !exclam) {
+               /*
+                * upgrade to a exclusive lock. if can't get, someone else 
+                * has the exclusive lock. bitch to the user.
+                */
+               if (flock(*iop, LOCK_EX|LOCK_NB) < 0 && errno == EWOULDBLOCK)
+       error (" File being modified by another process - use \"w!\" to write");
+                else *lp = LOCK_EX ;
+       }
+#endif FLOCKFILE
 #ifdef V6
                io = creat(file, 0644);
 #else
                io = creat(file, 0666);
 #ifdef V6
                io = creat(file, 0644);
 #else
                io = creat(file, 0666);
+#ifdef vms     /* to retain file protection modes on newer version of file */
+               if (!nonexist)
+                       chmod(file, stbuf.st_mode & 0777);
+#endif
 #endif
                if (io < 0)
                        syserror();
                writing = 1;
                if (hush == 0)
                        if (nonexist)
 #endif
                if (io < 0)
                        syserror();
                writing = 1;
                if (hush == 0)
                        if (nonexist)
-                               printf(" [New file]");
+                               ex_printf(" [New file]");
                        else if (value(WRITEANY) && edfile() != EDF)
                        else if (value(WRITEANY) && edfile() != EDF)
-                               printf(" [Existing file]");
+                               ex_printf(" [Existing file]");
+#ifdef FLOCKFILE
+               if (!*iop)
+                       *iop = dup(io) ;
+#endif FLOCKFILE
                break;
 
        case 2:
                break;
 
        case 2:
@@ -587,14 +765,36 @@ cre:
                        syserror();
                }
                lseek(io, 0l, 2);
                        syserror();
                }
                lseek(io, 0l, 2);
+#ifdef FLOCKFILE
+               if (!*iop) *iop = dup(io) ;
+               if (*lp != LOCK_EX && !exclam) {
+                       /*
+                        * upgrade to a exclusive lock. if can't get,
+                        * someone else has the exclusive lock.
+                        * bitch to the user.
+                        */
+                       if (flock(*iop, LOCK_SH|LOCK_NB) < 0
+                       && errno == EWOULDBLOCK)
+                               error (
+" File being modified by another process - use \"w!>>\" to write");
+                       else *lp = LOCK_EX ;
+               }
+#endif FLOCKFILE
                break;
        }
                break;
        }
+#ifdef FLOCKFILE
+       if (flock(*iop, LOCK_EX|LOCK_NB) >= 0)
+               *lp = LOCK_EX ;
+#endif FLOCKFILE
        putfile(0);
        putfile(0);
+#ifndef        vms
+       (void) fsync(io);
+#endif
        ignore(iostats());
        if (c != 2 && addr1 == one && addr2 == dol) {
                if (eq(file, savedfile))
                        edited = 1;
        ignore(iostats());
        if (c != 2 && addr1 == one && addr2 == dol) {
                if (eq(file, savedfile))
                        edited = 1;
-               sync();
+               ex_sync();
        }
        if (!dofname) {
                addr1 = saddr1;
        }
        if (!dofname) {
                addr1 = saddr1;
@@ -631,23 +831,24 @@ getfile()
        fp = nextip;
        do {
                if (--ninbuf < 0) {
        fp = nextip;
        do {
                if (--ninbuf < 0) {
-                       ninbuf = read(io, genbuf, LBSIZE) - 1;
+                       ninbuf = read(io, genbuf, (int) bsize) - 1;
                        if (ninbuf < 0) {
                                if (lp != linebuf) {
                                        lp++;
                        if (ninbuf < 0) {
                                if (lp != linebuf) {
                                        lp++;
-                                       printf(" [Incomplete last line]");
+                                       ex_printf(" [Incomplete last line]");
                                        break;
                                }
                                return (EOF);
                        }
 #ifdef CRYPT
                                        break;
                                }
                                return (EOF);
                        }
 #ifdef CRYPT
-                       fp = genbuf;
-                       while(fp < &genbuf[ninbuf]) {
-                               if (*fp++ & 0200) {
-                                       if (kflag)
+                       if (kflag) {
+                               fp = genbuf;
+                               while(fp < &genbuf[ninbuf]) {
+                                       if (*fp++ & 0200) {
                                                crblock(perm, genbuf, ninbuf+1,
                                                crblock(perm, genbuf, ninbuf+1,
-cntch);
-                                       break;
+       cntch);
+                                               break;
+                                       }
                                }
                        }
 #endif
                                }
                        }
 #endif
@@ -679,19 +880,28 @@ cntch);
 /*
  * Write a range onto the io stream.
  */
 /*
  * Write a range onto the io stream.
  */
+/* ARGSUSED */
 putfile(isfilter)
 int isfilter;
 {
        line *a1;
        register char *fp, *lp;
        register int nib;
 putfile(isfilter)
 int isfilter;
 {
        line *a1;
        register char *fp, *lp;
        register int nib;
+       struct stat statb;
 
        a1 = addr1;
        clrstats();
        cntln = addr2 - a1 + 1;
        if (cntln == 0)
                return;
 
        a1 = addr1;
        clrstats();
        cntln = addr2 - a1 + 1;
        if (cntln == 0)
                return;
-       nib = BUFSIZ;
+       if (fstat(io, &statb) < 0)
+               bsize = LBSIZE;
+       else {
+               bsize = statb.st_blksize;
+               if (bsize <= 0)
+                       bsize = LBSIZE;
+       }
+       nib = bsize;
        fp = genbuf;
        do {
                getline(*a1++);
        fp = genbuf;
        do {
                getline(*a1++);
@@ -707,7 +917,7 @@ int isfilter;
                                        wrerror();
                                }
                                cntch += nib;
                                        wrerror();
                                }
                                cntch += nib;
-                               nib = BUFSIZ - 1;
+                               nib = bsize - 1;
                                fp = genbuf;
                        }
                        if ((*fp++ = *lp++) == 0) {
                                fp = genbuf;
                        }
                        if ((*fp++ = *lp++) == 0) {
@@ -753,7 +963,8 @@ source(fil, okfail)
 {
        jmp_buf osetexit;
        register int saveinp, ointty, oerrno;
 {
        jmp_buf osetexit;
        register int saveinp, ointty, oerrno;
-       char savepeekc, *saveglobp;
+       char *saveglobp;
+       short savepeekc;
 
        signal(SIGINT, SIG_IGN);
        saveinp = dup(0);
 
        signal(SIGINT, SIG_IGN);
        saveinp = dup(0);
@@ -826,20 +1037,20 @@ iostats()
        io = -1;
        if (hush == 0) {
                if (value(TERSE))
        io = -1;
        if (hush == 0) {
                if (value(TERSE))
-                       printf(" %d/%D", cntln, cntch);
+                       ex_printf(" %d/%D", cntln, cntch);
                else
                else
-                       printf(" %d line%s, %D character%s", cntln, plural((long) cntln),
+                       ex_printf(" %d line%s, %D character%s", cntln, plural((long) cntln),
                            cntch, plural(cntch));
                if (cntnull || cntodd) {
                            cntch, plural(cntch));
                if (cntnull || cntodd) {
-                       printf(" (");
+                       ex_printf(" (");
                        if (cntnull) {
                        if (cntnull) {
-                               printf("%D null", cntnull);
+                               ex_printf("%D null", cntnull);
                                if (cntodd)
                                if (cntodd)
-                                       printf(", ");
+                                       ex_printf(", ");
                        }
                        if (cntodd)
                        }
                        if (cntodd)
-                               printf("%D non-ASCII", cntodd);
-                       putchar(')');
+                               ex_printf("%D non-ASCII", cntodd);
+                       ex_putchar(')');
                }
                noonl();
                flush();
                }
                noonl();
                flush();
@@ -847,25 +1058,37 @@ iostats()
        return (cntnull != 0 || cntodd != 0);
 }
 
        return (cntnull != 0 || cntodd != 0);
 }
 
-#if USG | USG3TTY
-/* It's so wonderful how we all speak the same language... */
+#ifdef USG
+# define index strchr
+# define rindex strrchr
+#endif
+#ifdef USG3TTY
+# define index strchr
+# define rindex strrchr
+#endif
+#ifdef vms
 # define index strchr
 # define rindex strrchr
 #endif
 
 # define index strchr
 # define rindex strrchr
 #endif
 
-checkmodeline(line)
-char *line;
+checkmodeline(l)
+char *l;
 {
        char *beg, *end;
        char cmdbuf[1024];
 {
        char *beg, *end;
        char cmdbuf[1024];
-       char *index(), *rindex();
+       char *index(), *rindex(), *strncpy();
 
 
-       beg = index(line, ':');
+       beg = index(l, ':');
        if (beg == NULL)
                return;
        if (beg == NULL)
                return;
-       if (beg[-2] != 'e' && beg[-2] != 'v') return;
-       if (beg[-1] != 'x' && beg[-1] != 'i') return;
-
+       if (&beg[-3] < l)
+               return;
+       if (!(  ( (beg[-3] == ' ' || beg[-3] == '\t')
+               && beg[-2] == 'e'
+               && beg[-1] == 'x')
+            || ( (beg[-3] == ' ' || beg[-3] == '\t')
+               && beg[-2] == 'v'
+               && beg[-1] == 'i'))) return;
        strncpy(cmdbuf, beg+1, sizeof cmdbuf);
        end = rindex(cmdbuf, ':');
        if (end == NULL)
        strncpy(cmdbuf, beg+1, sizeof cmdbuf);
        end = rindex(cmdbuf, ':');
        if (end == NULL)