X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/2b84abb596f52ab2068d52108adc96838ad4340a..31cef89cb428866f787983e68246030321893df4:/usr/src/cmd/ex/ex_io.c diff --git a/usr/src/cmd/ex/ex_io.c b/usr/src/cmd/ex/ex_io.c index d22f82ef87..e4fbb20845 100644 --- a/usr/src/cmd/ex/ex_io.c +++ b/usr/src/cmd/ex/ex_io.c @@ -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" @@ -6,7 +7,7 @@ #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; +short isalt; 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); - 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 { @@ -84,6 +89,8 @@ filename(comm) if (file[0] != 0) { lprintf("\"%s\"", file); if (comm == 'f') { + if (value(READONLY)) + printf(" [Read only]"); if (!edited) printf(" [Not edited]"); if (tchng) @@ -138,7 +145,7 @@ getargs() switch (c) { case '\\': - if (any(peekchar(), "#%")) + if (any(peekchar(), "#%|")) c = getchar(); /* fall into... */ @@ -218,6 +225,8 @@ glob(gp) 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)); @@ -248,7 +257,7 @@ glob(gp) } 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; + 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)) @@ -320,18 +342,33 @@ rop(c) 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"); @@ -342,11 +379,26 @@ rop(c) 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); @@ -389,13 +441,17 @@ other: 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(); } @@ -442,6 +498,8 @@ bool dofname; /* if 1 call filename, else use savedfile */ 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; @@ -457,7 +515,8 @@ bool dofname; /* if 1 call filename, else use savedfile */ switch (c) { case 0: - if (!exclam && !value(WRITEANY)) switch (edfile()) { + if (!exclam && (!value(WRITEANY) || value(READONLY))) + switch (edfile()) { case NOTEDF: if (nonexist) @@ -476,7 +535,14 @@ bool dofname; /* if 1 call filename, else use savedfile */ 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: @@ -490,6 +556,7 @@ cre: #endif if (io < 0) syserror(); + writing = 1; if (hush == 0) if (nonexist) printf(" [New file]"); @@ -518,6 +585,7 @@ cre: addr1 = saddr1; addr2 = saddr2; } + writing = 0; } /* @@ -534,317 +602,6 @@ edfile() 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. */ @@ -862,12 +619,25 @@ getfile() 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"); @@ -885,7 +655,6 @@ getfile() } *lp++ = c; } while (c != '\n'); - cntch += lp - linebuf; *--lp = 0; nextip = fp; cntln++; @@ -914,6 +683,10 @@ putfile() for (;;) { if (--nib < 0) { nib = fp - genbuf; +#ifdef CRYPT + if(kflag) + crblock(perm, genbuf, nib, cntch); +#endif if (write(io, genbuf, nib) != nib) { wrerror(); } @@ -928,6 +701,10 @@ putfile() } } while (a1 <= addr2); nib = fp - genbuf; +#ifdef CRYPT + if(kflag) + crblock(perm, genbuf, nib, cntch); +#endif 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. */ -static short slevel; +short slevel; +short ttyindes; source(fil, okfail) char *fil; @@ -959,12 +737,17 @@ source(fil, okfail) { 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; @@ -998,6 +781,8 @@ source(fil, okfail) close(0); dup(saveinp); close(saveinp); + globp = saveglobp; + peekc = savepeekc; slevel--; resexit(osetexit); }