/* * Write a file. */ void wop(bool dofname) /* bool dofname; / * if 1 call filename, else use savedfile */ { register int c, exclam, nonexist; line *saddr1, *saddr2; struct stat stbuf; c = 0; exclam = 0; if (dofname) { if (peekchar() == '!') exclam++, ignchar(); ignore(skipwh()); while (peekchar() == '>') ignchar(), c++, ignore(skipwh()); if (c != 0 && c != 2) 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; addr2=dol; CP(file, savedfile); if (inopen) { vclrech(0); splitw++; } lprintf("\"%s\"", file); } nonexist = stat(file, &stbuf); switch (c) { case 0: if (!exclam && (!value(WRITEANY) || value(READONLY))) switch (edfile()) { case NOTEDF: if (nonexist) break; if ((stbuf.st_mode & S_IFMT) == S_IFCHR) { if (samei(&stbuf, "/dev/null")) break; if (samei(&stbuf, "/dev/tty")) break; } io = open(file, O_WRONLY); if (io < 0) syserror(); if (!isatty(io)) serror(" File exists| File exists - use \"w! %s\" to overwrite", file); 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: /* synctmp(); */ #ifdef V6 io = creat(file, 0644); #else io = creat(file, 0666); #endif if (io < 0) syserror(); writing = 1; if (hush == 0) { if (nonexist) ex_printf(" [New file]"); else if (value(WRITEANY) && edfile() != EDF) ex_printf(" [Existing file]"); } break; case 2: io = open(file, O_WRONLY); if (io < 0) { if (exclam || value(WRITEANY)) goto cre; syserror(); } lseek(io, 0l, SEEK_END); break; } putfile(); ignore(iostats()); if (c != 2 && addr1 == one && addr2 == dol) { if (eq(file, savedfile)) edited = 1; ex_sync(); } if (!dofname) { addr1 = saddr1; addr2 = saddr2; } writing = 0; }
/* * Read a file from the world. * C is command, 'e' if this really an edit (or a recover). */ void rop(int 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, O_RDONLY); if (io < 0) { 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) { ex_printf(" [New file]"); noonl(); return; } } syserror(); } if (fstat(io, &stbuf)) syserror(); switch (stbuf.st_mode & S_IFMT) { case S_IFBLK: error(" Block special file"); case S_IFCHR: if (isatty(io)) error(" Teletype"); if (samei(&stbuf, "/dev/null")) break; error(" Character special file"); case S_IFDIR: error(" Directory"); case S_IFREG: #ifdef CRYPT if (xflag) break; #endif i = read(io, (char *) &magic, sizeof(magic)); lseek(io, 0l, SEEK_SET); if (i != sizeof(magic)) break; switch (magic) { 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. */ #if 0 case 0177545: case 0177555: error(" Archive"); #endif default: #ifndef BIT8 if (magic & 0100200) error(" Non-ascii file"); #endif 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)) { ex_printf(" [Read only]"); flush(); } if (c == 'r') setdot(); else setall(); if (FIXUNDO && inopen && c == 'r') undap1 = undap2 = dot + 1; rop2(); rop3(c); }
/* * Write a file. */ void wop(bool dofname) /* bool dofname; / * if 1 call filename, else use savedfile */ { register int c, exclam, nonexist; line *saddr1, *saddr2; struct stat stbuf; #ifdef FLOCKFILE int *lp, *iop ; #endif c = 0; exclam = 0; saddr1=addr1; saddr2=addr2; if (dofname) { if (peekchar() == '!') exclam++, ignchar(); ignore(skipwh()); while (peekchar() == '>') ignchar(), c++, ignore(skipwh()); if (c != 0 && c != 2) error("Write forms are 'w' and 'w>>'"); filename('w'); } else { if (savedfile[0] == 0) error("No file|No current filename"); addr1=one; addr2=dol; CP(file, savedfile); if (inopen) { vclrech(0); splitw++; } 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, O_WRONLY)) < 0) *iop = 0 ; } #endif switch (c) { case 0: if (!exclam && (!value(WRITEANY) || value(READONLY))) switch (edfile()) { case NOTEDF: if (nonexist) break; if ((stbuf.st_mode & S_IFMT) == S_IFCHR) { if (samei(&stbuf, _PATH_DEVNULL)) break; if (samei(&stbuf, _PATH_TTY)) break; } io = open(file, O_WRONLY); if (io < 0) syserror(); if (!isatty(io)) serror(" File exists| File exists - use \"w! %s\" to overwrite", file); 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: /* 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 #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) ex_printf(" [New file]"); else if (value(WRITEANY) && edfile() != EDF) ex_printf(" [Existing file]"); } #ifdef FLOCKFILE if (!*iop) *iop = dup(io) ; #endif break; case 2: io = open(file, O_WRONLY); if (io < 0) { if (exclam || value(WRITEANY)) goto cre; syserror(); } lseek(io, 0l, SEEK_END); #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 break; } #ifdef FLOCKFILE if (flock(*iop, LOCK_EX|LOCK_NB) >= 0) *lp = LOCK_EX ; #endif putfile(0); #ifndef vms (void) fsync(io); #endif ignore(iostats()); if (c != 2 && addr1 == one && addr2 == dol) { if (eq(file, savedfile)) edited = 1; ex_sync(); } if (!dofname) { addr1 = saddr1; addr2 = saddr2; } writing = 0; }
/* * Read a file from the world. * C is command, 'e' if this really an edit (or a recover). */ void rop(int c) { int i; struct stat64 stbuf; short magic; static int ovro; /* old value(vi_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) { edited++; /* * If the user just did "ex foo" they're probably * creating a new file. Don't be an error, since * this is ugly, and it messes up the + option. */ if (!seenprompt) { viprintf(gettext(" [New file]")); noonl(); return; } } if (value(vi_READONLY) && denied) { value(vi_READONLY) = ovro; denied = 0; } syserror(0); } if (fstat64(io, &stbuf)) syserror(0); switch (FTYPE(stbuf) & S_IFMT) { case S_IFBLK: error(gettext(" Block special file")); /* FALLTHROUGH */ case S_IFCHR: if (isatty(io)) error(gettext(" Teletype")); if (samei(&stbuf, "/dev/null")) break; error(gettext(" Character special file")); /* FALLTHROUGH */ case S_IFDIR: error(gettext(" Directory")); } if (c != 'r') { if (value(vi_READONLY) && denied) { value(vi_READONLY) = ovro; denied = 0; } if ((FMODE(stbuf) & 0222) == 0 || access((char *)file, 2) < 0) { ovro = value(vi_READONLY); denied = 1; value(vi_READONLY) = 1; } } if (hush == 0 && value(vi_READONLY)) { viprintf(gettext(" [Read only]")); flush(); } if (c == 'r') setdot(); else setall(); /* If it is a read command, then we must set dot to addr1 * (value of N in :Nr ). In the default case, addr1 will * already be set to dot. * * Next, it is necessary to mark the beginning (undap1) and * ending (undap2) addresses affected (for undo). Note that * rop2() and rop3() will adjust the value of undap2. */ if (FIXUNDO && inopen && c == 'r') { dot = addr1; undap1 = undap2 = dot + 1; } rop2(); rop3(c); }
/* * Read a file from the world. * C is command, 'e' if this really an edit (or a recover). */ void rop(int c) { struct stat stbuf; #ifndef __sun register int i; struct exec head; #endif static int ovro; /* old value(READONLY) */ static int denied; /* 1 if READONLY was set due to file permissions */ #ifdef FLOCKFILE int *lp, *iop; #endif io = open(file, O_RDONLY); if (io < 0) { 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) { ex_printf(" [New file]"); noonl(); return; } } syserror(); } if (fstat(io, &stbuf)) syserror(); switch (stbuf.st_mode & S_IFMT) { case S_IFBLK: error(" Block special file"); case S_IFCHR: if (isatty(io)) error(" Teletype"); if (samei(&stbuf, _PATH_DEVNULL)) break; error(" Character special file"); case S_IFDIR: error(" Directory"); #ifndef __sun case S_IFREG: #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 switch ( #if defined N_MAGIC N_MAGIC( #elif defined N_GETMAGIC N_GETMAGIC( #else # error #endif head)) { case 0405: /* data overlay on exec */ case OMAGIC: /* unshared */ case NMAGIC: /* shared text */ case 0411: /* separate I/D */ case ZMAGIC: /* 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"); case 070707: error(" Cpio file"); default: { 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 } break; } #endif /* __sun */ #endif } 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)) { 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 if (c == 'r') setdot(); else setall(); if (FIXUNDO && inopen && c == 'r') undap1 = undap2 = dot + 1; rop2(); rop3(c); }