-/* 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_vis.h"
/*
- * File input/output, unix escapes, source, filtering preserve and recover
+ * File input/output, source, preserve and recover
*/
/*
int altdot;
int oldadot;
bool wasalt;
+short isalt;
long cntch; /* Count of characters on unit io */
#ifndef VMUNIX
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;
+ if (c == 'e' || c == 'E')
+ altdot = lineDOT();
if (d == EOF)
ungetchar(d);
} else {
if (file[0] != 0) {
lprintf("\"%s\"", file);
if (comm == 'f') {
+ if (value(READONLY))
+ printf(" [Read only]");
if (!edited)
printf(" [Not edited]");
if (tchng)
switch (c) {
case '\\':
- if (any(peekchar(), "#%"))
+ if (any(peekchar(), "#%|"))
c = getchar();
/* fall into... */
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));
} while (c >= 0);
waitfor();
if (gp->argc0 == 0)
- error(NOSTR);
+ error("No match");
}
/*
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) {
- if (c == 'e' && errno == ENOENT)
+ if (c == 'e' && errno == ENOENT) {
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))
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) {
- 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");
+ /*
+ * 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");
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 (inopen && c == 'r')
+ if (FIXUNDO && inopen && c == 'r')
undap1 = undap2 = dot + 1;
rop2();
rop3(c);
dot = one;
markpr(one);
}
- undkind = UNDNONE;
+ if(FIXUNDO)
+ undkind = UNDNONE;
if (inopen) {
vcline = 0;
vreplace(0, LINES, lineDOL());
}
}
if (laste) {
+#ifdef VMUNIX
+ tlaste();
+#endif
laste = 0;
sync();
}
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;
switch (c) {
case 0:
- if (!exclam && !value(WRITEANY)) switch (edfile()) {
+ if (!exclam && (!value(WRITEANY) || value(READONLY)))
+ switch (edfile()) {
case NOTEDF:
if (nonexist)
close(io);
break;
+ case EDF:
+ if (value(READONLY))
+ error(" File is read only");
+ break;
+
case PARTBUF:
+ if (value(READONLY))
+ error(" File is read only");
error(" Use \"w!\" to write partial buffer");
}
cre:
#endif
if (io < 0)
syserror();
+ writing = 1;
if (hush == 0)
if (nonexist)
printf(" [New file]");
addr1 = saddr1;
addr2 = saddr2;
}
+ writing = 0;
}
/*
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.
*/
ninbuf = read(io, genbuf, LBSIZE) - 1;
if (ninbuf < 0) {
if (lp != linebuf) {
+ lp++;
printf(" [Incomplete last line]");
break;
}
return (EOF);
}
+#ifdef CRYPT
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");
}
*lp++ = c;
} while (c != '\n');
- cntch += lp - linebuf;
*--lp = 0;
nextip = fp;
cntln++;
for (;;) {
if (--nib < 0) {
nib = fp - genbuf;
+#ifdef CRYPT
+ if(kflag)
+ crblock(perm, genbuf, nib, cntch);
+#endif
if (write(io, genbuf, nib) != nib) {
wrerror();
}
}
} while (a1 <= addr2);
nib = fp - genbuf;
+#ifdef CRYPT
+ if(kflag)
+ crblock(perm, genbuf, nib, cntch);
+#endif
if (write(io, genbuf, nib) != nib) {
wrerror();
}
* 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;
{
jmp_buf osetexit;
register int saveinp, ointty, oerrno;
- int oprompt;
+ char savepeekc, *saveglobp;
signal(SIGINT, SIG_IGN);
saveinp = dup(0);
+ savepeekc = peekc;
+ saveglobp = globp;
+ peekc = 0; globp = 0;
if (saveinp < 0)
error("Too many nested sources");
+ if (slevel <= 0)
+ ttyindes = saveinp;
close(0);
if (open(fil, 0) < 0) {
oerrno = errno;
close(0);
dup(saveinp);
close(saveinp);
+ globp = saveglobp;
+ peekc = savepeekc;
slevel--;
resexit(osetexit);
}