BSD 4 release
[unix-history] / usr / src / cmd / ex / ex_io.c
index d22f82e..e4fbb20 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (c) 1979 Regents of the University of California */
+/* Copyright (c) 1980 Regents of the University of California */
+static char *sccsid = "@(#)ex_io.c     6.2 10/23/80";
 #include "ex.h"
 #include "ex_argv.h"
 #include "ex_temp.h"
 #include "ex.h"
 #include "ex_argv.h"
 #include "ex_temp.h"
@@ -6,7 +7,7 @@
 #include "ex_vis.h"
 
 /*
 #include "ex_vis.h"
 
 /*
- * File input/output, unix escapes, source, filtering preserve and recover
+ * File input/output, source, preserve and recover
  */
 
 /*
  */
 
 /*
@@ -16,6 +17,7 @@
 int    altdot;
 int    oldadot;
 bool   wasalt;
 int    altdot;
 int    oldadot;
 bool   wasalt;
+short  isalt;
 
 long   cntch;                  /* Count of characters on unit io */
 #ifndef VMUNIX
 
 long   cntch;                  /* Count of characters on unit io */
 #ifndef VMUNIX
@@ -42,8 +44,11 @@ filename(comm)
                if (savedfile[0] == 0 && comm != 'f')
                        error("No file|No current filename");
                CP(file, savedfile);
                if (savedfile[0] == 0 && comm != 'f')
                        error("No file|No current filename");
                CP(file, savedfile);
-               wasalt = 0;
+               wasalt = (isalt > 0) ? isalt-1 : 0;
+               isalt = 0;
                oldadot = altdot;
                oldadot = altdot;
+               if (c == 'e' || c == 'E')
+                       altdot = lineDOT();
                if (d == EOF)
                        ungetchar(d);
        } else {
                if (d == EOF)
                        ungetchar(d);
        } else {
@@ -84,6 +89,8 @@ filename(comm)
        if (file[0] != 0) {
                lprintf("\"%s\"", file);
                if (comm == 'f') {
        if (file[0] != 0) {
                lprintf("\"%s\"", file);
                if (comm == 'f') {
+                       if (value(READONLY))
+                               printf(" [Read only]");
                        if (!edited)
                                printf(" [Not edited]");
                        if (tchng)
                        if (!edited)
                                printf(" [Not edited]");
                        if (tchng)
@@ -138,7 +145,7 @@ getargs()
                switch (c) {
 
                case '\\':
                switch (c) {
 
                case '\\':
-                       if (any(peekchar(), "#%"))
+                       if (any(peekchar(), "#%|"))
                                c = getchar();
                        /* fall into... */
 
                                c = getchar();
                        /* fall into... */
 
@@ -218,6 +225,8 @@ glob(gp)
                close(1);
                dup(pvec[1]);
                close(pvec[0]);
                close(1);
                dup(pvec[1]);
                close(pvec[0]);
+               close(2);       /* so errors don't mess up the screen */
+               open("/dev/null", 1);
                execl(svalue(SHELL), "sh", "-c", genbuf, 0);
                oerrno = errno; close(1); dup(2); errno = oerrno;
                filioerr(svalue(SHELL));
                execl(svalue(SHELL), "sh", "-c", genbuf, 0);
                oerrno = errno; close(1); dup(2); errno = oerrno;
                filioerr(svalue(SHELL));
@@ -248,7 +257,7 @@ glob(gp)
        } while (c >= 0);
        waitfor();
        if (gp->argc0 == 0)
        } while (c >= 0);
        waitfor();
        if (gp->argc0 == 0)
-               error(NOSTR);
+               error("No match");
 }
 
 /*
 }
 
 /*
@@ -295,11 +304,24 @@ rop(c)
        register int i;
        struct stat stbuf;
        short magic;
        register int i;
        struct stat stbuf;
        short magic;
+       static int ovro;        /* old value(READONLY) */
+       static int denied;      /* 1 if READONLY was set due to file permissions */
 
        io = open(file, 0);
        if (io < 0) {
 
        io = open(file, 0);
        if (io < 0) {
-               if (c == 'e' && errno == ENOENT)
+               if (c == 'e' && errno == ENOENT) {
                        edited++;
                        edited++;
+                       /*
+                        * If the user just did "ex foo" he is probably
+                        * creating a new file.  Don't be an error, since
+                        * this is ugly, and it screws up the + option.
+                        */
+                       if (!seenprompt) {
+                               printf(" [New file]");
+                               noonl();
+                               return;
+                       }
+               }
                syserror();
        }
        if (fstat(io, &stbuf))
                syserror();
        }
        if (fstat(io, &stbuf))
@@ -320,18 +342,33 @@ rop(c)
                error(" Directory");
 
        case S_IFREG:
                error(" Directory");
 
        case S_IFREG:
+#ifdef CRYPT
+               if (xflag)
+                       break;
+#endif
                i = read(io, (char *) &magic, sizeof(magic));
                lseek(io, 0l, 0);
                if (i != sizeof(magic))
                        break;
                switch (magic) {
 
                i = read(io, (char *) &magic, sizeof(magic));
                lseek(io, 0l, 0);
                if (i != sizeof(magic))
                        break;
                switch (magic) {
 
-               case 0405:
-               case 0407:
-               case 0410:
-               case 0411:
+               case 0405:      /* Interdata? overlay */
+               case 0407:      /* unshared */
+               case 0410:      /* shared text */
+               case 0411:      /* separate I/D */
+               case 0413:      /* VM/Unix demand paged */
+               case 0430:      /* PDP-11 Overlay shared */
+               case 0431:      /* PDP-11 Overlay sep I/D */
                        error(" Executable");
 
                        error(" Executable");
 
+               /*
+                * We do not forbid the editing of portable archives
+                * because it is reasonable to edit them, especially
+                * if they are archives of text files.  This is
+                * especially useful if you archive source files together
+                * and copy them to another system with ~%take, since
+                * the files sometimes show up munged and must be fixed.
+                */
                case 0177545:
                case 0177555:
                        error(" Archive");
                case 0177545:
                case 0177555:
                        error(" Archive");
@@ -342,11 +379,26 @@ rop(c)
                        break;
                }
        }
                        break;
                }
        }
+       if (c != 'r') {
+               if (value(READONLY) && denied) {
+                       value(READONLY) = ovro;
+                       denied = 0;
+               }
+               if ((stbuf.st_mode & 0222) == 0 || access(file, 2) < 0) {
+                       ovro = value(READONLY);
+                       denied = 1;
+                       value(READONLY) = 1;
+               }
+       }
+       if (value(READONLY)) {
+               printf(" [Read only]");
+               flush();
+       }
        if (c == 'r')
                setdot();
        else
                setall();
        if (c == 'r')
                setdot();
        else
                setall();
-       if (inopen && c == 'r')
+       if (FIXUNDO && inopen && c == 'r')
                undap1 = undap2 = dot + 1;
        rop2();
        rop3(c);
                undap1 = undap2 = dot + 1;
        rop2();
        rop3(c);
@@ -389,13 +441,17 @@ other:
                                        dot = one;
                                markpr(one);
                        }
                                        dot = one;
                                markpr(one);
                        }
-               undkind = UNDNONE;
+               if(FIXUNDO)
+                       undkind = UNDNONE;
                if (inopen) {
                        vcline = 0;
                        vreplace(0, LINES, lineDOL());
                }
        }
        if (laste) {
                if (inopen) {
                        vcline = 0;
                        vreplace(0, LINES, lineDOL());
                }
        }
        if (laste) {
+#ifdef VMUNIX
+               tlaste();
+#endif
                laste = 0;
                sync();
        }
                laste = 0;
                sync();
        }
@@ -442,6 +498,8 @@ bool dofname;       /* if 1 call filename, else use savedfile */
                        error("Write forms are 'w' and 'w>>'");
                filename('w');
        } else {
                        error("Write forms are 'w' and 'w>>'");
                filename('w');
        } else {
+               if (savedfile[0] == 0)
+                       error("No file|No current filename");
                saddr1=addr1;
                saddr2=addr2;
                addr1=one;
                saddr1=addr1;
                saddr2=addr2;
                addr1=one;
@@ -457,7 +515,8 @@ bool dofname;       /* if 1 call filename, else use savedfile */
        switch (c) {
 
        case 0:
        switch (c) {
 
        case 0:
-               if (!exclam && !value(WRITEANY)) switch (edfile()) {
+               if (!exclam && (!value(WRITEANY) || value(READONLY)))
+               switch (edfile()) {
                
                case NOTEDF:
                        if (nonexist)
                
                case NOTEDF:
                        if (nonexist)
@@ -476,7 +535,14 @@ bool dofname;      /* if 1 call filename, else use savedfile */
                        close(io);
                        break;
 
                        close(io);
                        break;
 
+               case EDF:
+                       if (value(READONLY))
+                               error(" File is read only");
+                       break;
+
                case PARTBUF:
                case PARTBUF:
+                       if (value(READONLY))
+                               error(" File is read only");
                        error(" Use \"w!\" to write partial buffer");
                }
 cre:
                        error(" Use \"w!\" to write partial buffer");
                }
 cre:
@@ -490,6 +556,7 @@ cre:
 #endif
                if (io < 0)
                        syserror();
 #endif
                if (io < 0)
                        syserror();
+               writing = 1;
                if (hush == 0)
                        if (nonexist)
                                printf(" [New file]");
                if (hush == 0)
                        if (nonexist)
                                printf(" [New file]");
@@ -518,6 +585,7 @@ cre:
                addr1 = saddr1;
                addr2 = saddr2;
        }
                addr1 = saddr1;
                addr2 = saddr2;
        }
+       writing = 0;
 }
 
 /*
 }
 
 /*
@@ -534,317 +602,6 @@ edfile()
        return (addr1 == one && addr2 == dol ? EDF : PARTBUF);
 }
 
        return (addr1 == one && addr2 == dol ? EDF : PARTBUF);
 }
 
-/*
- * First part of a shell escape,
- * parse the line, expanding # and % and ! and printing if implied.
- */
-unix0(warn)
-       bool warn;
-{
-       register char *up, *fp;
-       register short c;
-       char printub, puxb[UXBSIZE + sizeof (int)];
-
-       printub = 0;
-       CP(puxb, uxb);
-       c = getchar();
-       if (c == '\n' || c == EOF)
-               error("Incomplete shell escape command@- use 'shell' to get a shell");
-       up = uxb;
-       do {
-               switch (c) {
-
-               case '\\':
-                       if (any(peekchar(), "%#!"))
-                               c = getchar();
-               default:
-                       if (up >= &uxb[UXBSIZE]) {
-tunix:
-                               uxb[0] = 0;
-                               error("Command too long");
-                       }
-                       *up++ = c;
-                       break;
-
-               case '!':
-                       fp = puxb;
-                       if (*fp == 0) {
-                               uxb[0] = 0;
-                               error("No previous command@to substitute for !");
-                       }
-                       printub++;
-                       while (*fp) {
-                               if (up >= &uxb[UXBSIZE])
-                                       goto tunix;
-                               *up++ = *fp++;
-                       }
-                       break;
-
-               case '#':
-                       fp = altfile;
-                       if (*fp == 0) {
-                               uxb[0] = 0;
-                               error("No alternate filename@to substitute for #");
-                       }
-                       goto uexp;
-
-               case '%':
-                       fp = savedfile;
-                       if (*fp == 0) {
-                               uxb[0] = 0;
-                               error("No filename@to substitute for %%");
-                       }
-uexp:
-                       printub++;
-                       while (*fp) {
-                               if (up >= &uxb[UXBSIZE])
-                                       goto tunix;
-                               *up++ = *fp++ | QUOTE;
-                       }
-                       break;
-               }
-               c = getchar();
-       } while (c == '|' || !endcmd(c));
-       if (c == EOF)
-               ungetchar(c);
-       *up = 0;
-       if (!inopen)
-               resetflav();
-       if (warn)
-               ckaw();
-       if (warn && hush == 0 && chng && xchng != chng && value(WARN) && dol > zero) {
-               xchng = chng;
-               vnfl();
-               printf(mesg("[No write]|[No write since last change]"));
-               noonl();
-               flush();
-       } else
-               warn = 0;
-       if (printub) {
-               if (uxb[0] == 0)
-                       error("No previous command@to repeat");
-               if (inopen) {
-                       splitw++;
-                       vclean();
-                       vgoto(WECHO, 0);
-               }
-               if (warn)
-                       vnfl();
-               if (hush == 0)
-                       lprintf("!%s", uxb);
-               if (inopen) {
-                       vclreol();
-                       vgoto(WECHO, 0);
-               } else
-                       putnl();
-               flush();
-       }
-}
-
-/*
- * Do the real work for execution of a shell escape.
- * Mode is like the number passed to open system calls
- * and indicates filtering.  If input is implied, newstdin
- * must have been setup already.
- */
-unixex(opt, up, newstdin, mode)
-       char *opt, *up;
-       int newstdin, mode;
-{
-       int pvec[2], f;
-
-       signal(SIGINT, SIG_IGN);
-       if (inopen)
-               f = setty(normf);
-       if ((mode & 1) && pipe(pvec) < 0) {
-               /* Newstdin should be io so it will be closed */
-               if (inopen)
-                       setty(f);
-               error("Can't make pipe for filter");
-       }
-#ifndef VFORK
-       pid = fork();
-#else
-       pid = vfork();
-#endif
-       if (pid < 0) {
-               if (mode & 1) {
-                       close(pvec[0]);
-                       close(pvec[1]);
-               }
-               setrupt();
-               error("No more processes");
-       }
-       if (pid == 0) {
-               if (mode & 2) {
-                       close(0);
-                       dup(newstdin);
-                       close(newstdin);
-               }
-               if (mode & 1) {
-                       close(pvec[0]);
-                       close(1);
-                       dup(pvec[1]);
-                       if (inopen) {
-                               close(2);
-                               dup(1);
-                       }
-                       close(pvec[1]);
-               }
-               if (io)
-                       close(io);
-               if (tfile)
-                       close(tfile);
-#ifndef VMUNIX
-               close(erfile);
-#endif
-               signal(SIGHUP, oldhup);
-               signal(SIGQUIT, oldquit);
-               if (ruptible)
-                       signal(SIGINT, SIG_DFL);
-               execl(svalue(SHELL), "sh", opt, up, (char *) 0);
-               printf("No %s!\n", svalue(SHELL));
-               error(NOSTR);
-       }
-       if (mode & 1) {
-               io = pvec[0];
-               close(pvec[1]);
-       }
-       if (newstdin)
-               close(newstdin);
-       return (f);
-}
-
-/*
- * Wait for the command to complete.
- * F is for restoration of tty mode if from open/visual.
- * C flags suppression of printing.
- */
-unixwt(c, f)
-       bool c;
-       int f;
-{
-
-       waitfor();
-       if (inopen)
-               setty(f);
-       setrupt();
-       if (!inopen && c && hush == 0) {
-               printf("!\n");
-               flush();
-               termreset();
-               gettmode();
-       }
-}
-
-/*
- * Setup a pipeline for the filtration implied by mode
- * which is like a open number.  If input is required to
- * the filter, then a child editor is created to write it.
- * If output is catch it from io which is created by unixex.
- */
-filter(mode)
-       register int mode;
-{
-       static int pvec[2];
-       register int f;
-       register int lines = lineDOL();
-
-       mode++;
-       if (mode & 2) {
-               signal(SIGINT, SIG_IGN);
-               if (pipe(pvec) < 0)
-                       error("Can't make pipe");
-               pid = fork();
-               io = pvec[0];
-               if (pid < 0) {
-                       setrupt();
-                       close(pvec[1]);
-                       error("No more processes");
-               }
-               if (pid == 0) {
-                       setrupt();
-                       io = pvec[1];
-                       close(pvec[0]);
-                       putfile();
-                       exit(0);
-               }
-               close(pvec[1]);
-               io = pvec[0];
-               setrupt();
-       }
-       f = unixex("-c", uxb, (mode & 2) ? pvec[0] : 0, mode);
-       if (mode == 3) {
-               delete(0);
-               addr2 = addr1 - 1;
-       }
-       if (mode & 1) {
-               undap1 = undap2 = addr2+1;
-               ignore(append(getfile, addr2));
-       }
-       close(io);
-       io = -1;
-       unixwt(!inopen, f);
-       netchHAD(lines);
-}
-
-/*
- * Set up to do a recover, getting io to be a pipe from
- * the recover process.
- */
-recover()
-{
-       static int pvec[2];
-
-       if (pipe(pvec) < 0)
-               error(" Can't make pipe for recovery");
-       pid = fork();
-       io = pvec[0];
-       if (pid < 0) {
-               close(pvec[1]);
-               error(" Can't fork to execute recovery");
-       }
-       if (pid == 0) {
-               close(2);
-               dup(1);
-               close(1);
-               dup(pvec[1]);
-               close(pvec[1]);
-               execl(EXRECOVER, "exrecover", svalue(DIRECTORY), file, (char *) 0);
-               close(1);
-               dup(2);
-               error(" No recovery routine");
-       }
-       close(pvec[1]);
-}
-
-/*
- * Wait for the process (pid an external) to complete.
- */
-waitfor()
-{
-
-       do
-               rpid = wait(&status);
-       while (rpid != pid && rpid != -1);
-       status = (status >> 8) & 0377;
-}
-
-/*
- * The end of a recover operation.  If the process
- * exits non-zero, force not edited; otherwise force
- * a write.
- */
-revocer()
-{
-
-       waitfor();
-       if (pid == rpid && status != 0)
-               edited = 0;
-       else
-               change();
-}
-
 /*
  * Extract the next line from the io stream.
  */
 /*
  * Extract the next line from the io stream.
  */
@@ -862,12 +619,25 @@ getfile()
                        ninbuf = read(io, genbuf, LBSIZE) - 1;
                        if (ninbuf < 0) {
                                if (lp != linebuf) {
                        ninbuf = read(io, genbuf, LBSIZE) - 1;
                        if (ninbuf < 0) {
                                if (lp != linebuf) {
+                                       lp++;
                                        printf(" [Incomplete last line]");
                                        break;
                                }
                                return (EOF);
                        }
                                        printf(" [Incomplete last line]");
                                        break;
                                }
                                return (EOF);
                        }
+#ifdef CRYPT
                        fp = genbuf;
                        fp = genbuf;
+                       while(fp < &genbuf[ninbuf]) {
+                               if (*fp++ & 0200) {
+                                       if (kflag)
+                                               crblock(perm, genbuf, ninbuf+1,
+cntch);
+                                       break;
+                               }
+                       }
+#endif
+                       fp = genbuf;
+                       cntch += ninbuf+1;
                }
                if (lp >= &linebuf[LBSIZE]) {
                        error(" Line too long");
                }
                if (lp >= &linebuf[LBSIZE]) {
                        error(" Line too long");
@@ -885,7 +655,6 @@ getfile()
                }
                *lp++ = c;
        } while (c != '\n');
                }
                *lp++ = c;
        } while (c != '\n');
-       cntch += lp - linebuf;
        *--lp = 0;
        nextip = fp;
        cntln++;
        *--lp = 0;
        nextip = fp;
        cntln++;
@@ -914,6 +683,10 @@ putfile()
                for (;;) {
                        if (--nib < 0) {
                                nib = fp - genbuf;
                for (;;) {
                        if (--nib < 0) {
                                nib = fp - genbuf;
+#ifdef CRYPT
+                               if(kflag)
+                                        crblock(perm, genbuf, nib, cntch);
+#endif
                                if (write(io, genbuf, nib) != nib) {
                                        wrerror();
                                }
                                if (write(io, genbuf, nib) != nib) {
                                        wrerror();
                                }
@@ -928,6 +701,10 @@ putfile()
                }
        } while (a1 <= addr2);
        nib = fp - genbuf;
                }
        } while (a1 <= addr2);
        nib = fp - genbuf;
+#ifdef CRYPT
+       if(kflag)
+               crblock(perm, genbuf, nib, cntch);
+#endif
        if (write(io, genbuf, nib) != nib) {
                wrerror();
        }
        if (write(io, genbuf, nib) != nib) {
                wrerror();
        }
@@ -951,7 +728,8 @@ wrerror()
  * Source command, handles nested sources.
  * Traps errors since it mungs unit 0 during the source.
  */
  * Source command, handles nested sources.
  * Traps errors since it mungs unit 0 during the source.
  */
-static short slevel;
+short slevel;
+short ttyindes;
 
 source(fil, okfail)
        char *fil;
 
 source(fil, okfail)
        char *fil;
@@ -959,12 +737,17 @@ source(fil, okfail)
 {
        jmp_buf osetexit;
        register int saveinp, ointty, oerrno;
 {
        jmp_buf osetexit;
        register int saveinp, ointty, oerrno;
-       int oprompt;
+       char savepeekc, *saveglobp;
 
        signal(SIGINT, SIG_IGN);
        saveinp = dup(0);
 
        signal(SIGINT, SIG_IGN);
        saveinp = dup(0);
+       savepeekc = peekc;
+       saveglobp = globp;
+       peekc = 0; globp = 0;
        if (saveinp < 0)
                error("Too many nested sources");
        if (saveinp < 0)
                error("Too many nested sources");
+       if (slevel <= 0)
+               ttyindes = saveinp;
        close(0);
        if (open(fil, 0) < 0) {
                oerrno = errno;
        close(0);
        if (open(fil, 0) < 0) {
                oerrno = errno;
@@ -998,6 +781,8 @@ source(fil, okfail)
        close(0);
        dup(saveinp);
        close(saveinp);
        close(0);
        dup(saveinp);
        close(saveinp);
+       globp = saveglobp;
+       peekc = savepeekc;
        slevel--;
        resexit(osetexit);
 }
        slevel--;
        resexit(osetexit);
 }