BSD 4_4 release
[unix-history] / usr / src / usr.bin / ex / ex_io.c
index d3d9663..d38a673 100644 (file)
@@ -1,18 +1,24 @@
-/*
- * Copyright (c) 1980 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+/*-
+ * 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
  */
 
 #ifndef lint
-static char *sccsid = "@(#)ex_io.c     7.13 (Berkeley) %G%";
-#endif not 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
@@ -36,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
@@ -46,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 ;
+
+       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);
 
        d = ex_getchar();
        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;
@@ -77,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;
                }
@@ -103,6 +154,12 @@ filename(comm)
                                ex_printf(" [Not edited]");
                        if (tchng)
                                ex_printf(" [Modified]");
                                ex_printf(" [Not edited]");
                        if (tchng)
                                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
@@ -230,11 +287,16 @@ 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 */
-               ignore(open("/dev/null", 1));
+               ignore(open(_PATH_DEVNULL, 1));
                execl(svalue(SHELL), "sh", "-c", genbuf, 0);
                oerrno = errno;
                close(1);
                execl(svalue(SHELL), "sh", "-c", genbuf, 0);
                oerrno = errno;
                close(1);
@@ -277,17 +339,14 @@ glob(gp)
  */
 gscan()
 {
  */
 gscan()
 {
-#ifndef        vms
+#ifndef        vms                     /* Never have meta-characters in vms */
        register char *cp;
 
        for (cp = genbuf; *cp; cp++)
        register char *cp;
 
        for (cp = genbuf; *cp; cp++)
-               if (any(*cp, "~{[*?$`'\"\\"))
                if (any(*cp, "~{[*?$`'\"\\"))
                        return (1);
                if (any(*cp, "~{[*?$`'\"\\"))
                        return (1);
-       return (0);
-#else
-       return 0;       /* Never have meta-characters in vms */
 #endif
 #endif
+       return (0);
 }
 
 /*
 }
 
 /*
@@ -318,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) {
@@ -349,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");
 
@@ -357,18 +419,22 @@ rop(c)
                error(" Directory");
 
        case S_IFREG:
                error(" Directory");
 
        case S_IFREG:
-               i = read(io, (char *) &magic, sizeof(magic));
-               lseek(io, 0l, 0);
-               if (i != sizeof(magic))
+#ifdef CRYPT
+               if (xflag)
+                       break;
+#endif
+               i = read(io, (char *)&head, sizeof(head));
+               (void)lseek(io, 0L, L_SET);
+               if (i != sizeof(head))
                        break;
 #ifndef vms
                        break;
 #ifndef vms
-               switch (magic) {
+               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");
@@ -384,16 +450,21 @@ 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;
                }
 #endif
                        break;
                }
 #endif
@@ -413,6 +484,53 @@ rop(c)
                ex_printf(" [Read only]");
                flush();
        }
                ex_printf(" [Read only]");
                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
@@ -521,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;
@@ -548,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:
@@ -558,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);
@@ -585,10 +723,25 @@ 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();
 #endif
                if (io < 0)
                        syserror();
@@ -598,6 +751,10 @@ cre:
                                ex_printf(" [New file]");
                        else if (value(WRITEANY) && edfile() != EDF)
                                ex_printf(" [Existing file]");
                                ex_printf(" [New file]");
                        else if (value(WRITEANY) && edfile() != EDF)
                                ex_printf(" [Existing file]");
+#ifdef FLOCKFILE
+               if (!*iop)
+                       *iop = dup(io) ;
+#endif FLOCKFILE
                break;
 
        case 2:
                break;
 
        case 2:
@@ -608,8 +765,27 @@ 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);
 #ifndef        vms
        (void) fsync(io);
        putfile(0);
 #ifndef        vms
        (void) fsync(io);
@@ -664,6 +840,18 @@ getfile()
                                }
                                return (EOF);
                        }
                                }
                                return (EOF);
                        }
+#ifdef CRYPT
+                       if (kflag) {
+                               fp = genbuf;
+                               while(fp < &genbuf[ninbuf]) {
+                                       if (*fp++ & 0200) {
+                                               crblock(perm, genbuf, ninbuf+1,
+       cntch);
+                                               break;
+                                       }
+                               }
+                       }
+#endif
                        fp = genbuf;
                        cntch += ninbuf+1;
                }
                        fp = genbuf;
                        cntch += ninbuf+1;
                }
@@ -721,6 +909,10 @@ int isfilter;
                for (;;) {
                        if (--nib < 0) {
                                nib = fp - genbuf;
                for (;;) {
                        if (--nib < 0) {
                                nib = fp - genbuf;
+#ifdef CRYPT
+                               if(kflag && !isfilter)
+                                        crblock(perm, genbuf, nib, cntch);
+#endif
                                if (write(io, genbuf, nib) != nib) {
                                        wrerror();
                                }
                                if (write(io, genbuf, nib) != nib) {
                                        wrerror();
                                }
@@ -735,6 +927,10 @@ int isfilter;
                }
        } while (a1 <= addr2);
        nib = fp - genbuf;
                }
        } while (a1 <= addr2);
        nib = fp - genbuf;
+#ifdef CRYPT
+       if(kflag && !isfilter)
+               crblock(perm, genbuf, nib, cntch);
+#endif
        if (write(io, genbuf, nib) != nib) {
                wrerror();
        }
        if (write(io, genbuf, nib) != nib) {
                wrerror();
        }
@@ -875,17 +1071,17 @@ iostats()
 # define rindex strrchr
 #endif
 
 # define rindex strrchr
 #endif
 
-checkmodeline(line)
-char *line;
+checkmodeline(l)
+char *l;
 {
        char *beg, *end;
        char cmdbuf[1024];
        char *index(), *rindex(), *strncpy();
 
 {
        char *beg, *end;
        char cmdbuf[1024];
        char *index(), *rindex(), *strncpy();
 
-       beg = index(line, ':');
+       beg = index(l, ':');
        if (beg == NULL)
                return;
        if (beg == NULL)
                return;
-       if (&beg[-3] < line)
+       if (&beg[-3] < l)
                return;
        if (!(  ( (beg[-3] == ' ' || beg[-3] == '\t')
                && beg[-2] == 'e'
                return;
        if (!(  ( (beg[-3] == ' ' || beg[-3] == '\t')
                && beg[-2] == 'e'