📄 eefile.c
字号:
statres = stat(o_name,&statb); /* Get old file's info (if any) */#if IMAGEN /* Now, make sure someone hasn't written the file behind our backs */ if ((styp==WF_SBUFF) && !(flags&WF_ASK) && b->b_fn && stat(b->b_fn, &s) >= 0) if (s.st_mtime != b->b_mtime) { char *ans; ans = ask("Since you last read \"%s\", someone has changed it.\nDo you want to write it anyway (NOT RECOMMENDED!)? ", b->b_fn); if (ans == 0 || upcase(*ans) != 'Y') { ding("I suggest you either read it again, or\nwrite it to a temporary file, and merge the two versions manually."); if (ans) chkfree(ans); return(0); } if (ans) chkfree(ans); }#endif /*IMAGEN*/ /* Try to get around major UNIX screw of smashing files. * This still isn't perfect (screws up with long filenames) but... * 1. Write out to <newname> * 2. Rename <name> to <oldname> (may have to delete existing <oldname>) * 3. Rename <newname> to <name>. */ fncons(oldname,ev_fno1,o_name,ev_fno2); /* Set up "old" filename */ fncons(newname,ev_fnn1,o_name,ev_fnn2); /* Set up "new" filename */ unlink(newname); /* Ensure we don't clobber */ unhoard(); /* Now give up saved FD */#if !(V6) /* Standard V6 doesn't have access call */ if(statres >= 0) /* If file exists, */ { if(access(o_name, 2) != 0) /* check for write access */ { ferr_wopn(); res = 0; /* Failure */ goto wdone; } }#endif /*-V6*/#ifdef STDWRITE if(flags&WF_ASK) { if((o_file = fopen(newname, "w")) ==0) /* Create new output file */ { ferr_wopn(); res = 0; /* Failure */ goto wdone; } setbuf(o_file,obuf); /* Ensure always have buffer */ } else /* New stuff */#endif /*STDWRITE*/ {#if !(TOPS20) if((ofd = creat(newname,ev_filmod)) < 0)#else if((ofd = open(newname,O_WRONLY|O_UNCONVERTED)) < 0)#endif /*TOPS20*/ { ferr_wopn(); res = 0; /* Failure */ goto wdone; } } if (styp==WF_SBUFF) set_fn(o_name); /* Won, so set default fn for buff */#if IMAGEN saynow("Writing "); switch(styp) { case WF_SBUFF: saytoo(b->b_fn); break; case WF_SREG: saytoo("region"); break;#if FX_WLASTKILL case WF_SKILL: saytoo("last kill"); break;#endif } sayntoo("...");#else saynow("Writing...");#endif /*-IMAGEN*/#if !(TOPS20) /* T20 does all this already */ if(statres >= 0) /* Get old file's modes */ { /* Try to duplicate them */ /* Do chmod first since after changing owner we may not ** have permission to change mode, at least on V6. */ chmod(newname,statb.st_mode & 07777);#if V6 chown(newname, (statb.st_gid<<8)|(statb.st_uid&0377));#else chown(newname,statb.st_uid,statb.st_gid);#endif /*-V6*/ }#if V6 /* If no old file existed, and we are a V6 system, try to set * the modes explicitly. On V7 we're OK because the user can * diddle "umask" to get whatever is desired. * On TOPS-20 of course everything is all peachy. */ else chmod(newname, ev_filmod);#endif /*V6*/#endif /*TOPS20*/#ifdef STDWRITE if(flags&WF_ASK) { switch(styp) { case WF_SBUFF: dotcnt = e_blen(); e_gobob(); break; case WF_SREG: if((dotcnt = mark_dot - cur_dot) < 0) { e_goff(dotcnt); dotcnt = -dotcnt; } else e_gocur(); break; /* WF_SKILL not implemented here */ } while(--dotcnt >= 0) putc(sb_getc(((SBBUF *)b)), o_file); e_gocur(); fflush(o_file); /* Force everything out */ res = ferror(o_file); /* Save result of stuff */ fclose(o_file); /* Now flush FD */ } else /* New stuff */#endif /*STDWRITE*/ { switch(styp) { case WF_SBUFF: res = sb_fsave((SBBUF *)b, ofd); break; case WF_SREG: e_gocur(); sd = e_copyn((chroff)(mark_dot - cur_dot)); res = sbx_aout(sd, 2, ofd); sbs_del(sd); break;#if FX_WLASTKILL case WF_SKILL: res = sbx_aout(kill_ring[kill_ptr], 2, ofd); break;#endif } close(ofd); } if(errno = res) { ferr(" Output error"); res = 0; /* Failure */ goto wdone; } else res = 1; /* Success so far */ if(styp == WF_SBUFF) f_bufnotmod(); /* Reset "buffer modified" flag */ /* Here we effect the screw-prevention steps explained earlier. */ /* TOPS-20, with generation numbers, need not worry about this. */#if TOPS20 saynow("Written");#else /*-TOPS20*/#if IMAGEN /* KLH -- This conditional bracketting is prone to lossage */ /* Only create the .BAK file once per editing session!! */ if ((styp==WF_SBUFF) || !(b->b_flags & B_BACKEDUP)) { if (styp==WF_SBUFF) b->b_flags |= B_BACKEDUP;#endif /*IMAGEN*/ unlink(oldname); /* remove any existing "old" file */ if(link(o_name,oldname) == 0) /* Rename current to "old" */ unlink(o_name); /* Here is the critical point... if we stop here, there is no * longer any file with the appropriate filename!!! */#if IMAGEN } else unlink(o_name);#endif /*IMAGEN*/ if(link(newname,o_name) == 0) /* Rename "new" to current */ { unlink(newname);#if IMAGEN sayntoo("OK");#else saynow("Written");#endif /*-IMAGEN*/ } else { dingtoo("rename error!"); res = 0; }#endif /*-TOPS20*/#if IMAGEN /* Update the last-modified time for the file in this buffer */ if ((styp == WF_SBUFF) && b->b_fn) { stat(b->b_fn, &s); b->b_mtime = s.st_mtime; }#endif /*IMAGEN*/wdone: hoard(); /* Get back a retained FD */ return(res);}/* FNCONS(dest,pre,f_name,post) * Specialized routine to cons up a filename string into "dest", * given prefix and postfix strings to be added onto last component of * filename. */char *fncons(dest, pre, f_name, post)char *dest,*pre,*f_name,*post;{ register char *cp, *cp2; char *last_fname(); cp = dest; *cp = 0; /* Make dest string null initially */ cp2 = last_fname(f_name); /* Get pointer to beg of last name */ strncat(cp,f_name,cp2-f_name); /* Copy first part of filename */ if(pre) strcat(cp, pre); /* If prefix exists, add it on */ cp = last_fname(cp); /* Recheck in case levels added */ strcat(cp, cp2); /* Now add last name */ if(cp2 = post) /* If there's a postfix, must check */ { cp[FNAMELEN-strlen(cp2)] = 0; /* and cut dest so postfix */ strcat(cp, cp2); /* will fit on end. */ } return(dest);}/* LAST_FNAME(string) * Get the last component of a file name. Returns pointer to * start of component; does NOT copy string! */char *last_fname(f_name)char *f_name;{ register char *cp, *p; register int c; p = f_name; /* pointer to last slash */ cp = p; while(c = *cp++) if(c == '/') p = cp; /* point to after the slash */ return(p);}/* SET_FN(string) * Set the default filename for current buffer to "string". */set_fn (string)char *string;{ register struct buffer *b; register char *str;#if IMAGEN register char *cp; register int len;#endif /*IMAGEN*/ char *strdup(); b = cur_buf; str = strdup(string); /* Copy now in case copying self */ if(b->b_fn) chkfree(b->b_fn); b -> b_fn = str;#if IMAGEN /* Do mode determination based on file name (HACK HACK) */ len = strlen(str); b->b_flags &= ~(B_CMODE|B_TEXTMODE); if (len > 4) { if (strcmp(&str[len - 5], "draft") == 0) b->b_flags |= B_TEXTMODE; else { cp = &str[len - 4]; if (strcmp(cp, ".txt") == 0 || strcmp(cp, ".mss") == 0) b->b_flags |= B_TEXTMODE; } } if (len > 2) { cp = &str[len - 2]; if (strcmp(cp, ".h") == 0 || strcmp(cp, ".c") == 0) b->b_flags |= B_CMODE; }#endif /*IMAGEN*/ redp(RD_MODE);}/* SAVEWORLD - Attempt to save all changes user has made. * Currently this amounts to writing out all modified buffers * to the files $HOME/+buffername. If a buffer is given as argument, * only that buffer is saved. * This is only called from the error handling routines with * the TTY either gone or in normal (non-edit) mode. The "grunt" * flag says whether to output feedback during the saving process. */saveworld(bp, grunt)struct buffer *bp;int grunt;{ register struct buffer *b; register int wfd; char sfname[FNAMSIZ]; struct buffer *sel_mbuf(); unhoard(); /* Ensure a FD is free for writing */ if(b = bp) goto once; while(!bp && (b = sel_mbuf(b))) { once: strcat(strcat(strcpy(sfname,homedir),"/+"),b->b_name); if(grunt) printf("Saving %s...",sfname);#if !(TOPS20) if((wfd = creat(sfname, ev_filmod)) < 0)#else if((wfd = open(sfname,O_WRONLY|O_UNCONVERTED)) < 0)#endif /*TOPS20*/ { if(grunt) printf(" error - %s\n", strerror(errno)); } else { sb_fsave((SBBUF *)b, wfd); close(wfd); if(grunt) printf("\n"); } b->b_flags &= ~B_MODIFIED; } hoard();}/* HOARD, UNHOARD - Routines to save a FD for writing, to make sure * that we can always write out a buffer no matter how many * file descriptors we are currently using. */hoard() /* Stash away a FD */{ if(hoardfd <= 0)#if !(TOPS20) hoardfd = open("nul:", 1);#else hoardfd = open("/dev/null", 1);#endif}unhoard() /* Give up our stashed FD so it can be re-used */{ close(hoardfd); hoardfd = -1;}#if IMAGEN#include <pwd.h>#include <ctype.h>/* * expand_file: expand any ~user-name/ or $env-var/ prefixes in sfn, * producing the full name in dfn */expand_file(dfn, sfn)register char *dfn, *sfn;{ register char *sp, *tp; register int c; register struct passwd *pw; char ts[128]; /* HORRIBLE, GROSS, DISGUSTING HACK: if the destination and * source strings are identical (same pointer), then do not * do any expansion--this happens to work with the current * structure very well, since multiple expansions may happen. */ if (dfn == sfn) return; ts[0] = 0; /* If have a leading $, then expand environment variable */ if (*sfn == '$') { ++sfn; tp = ts; while (*tp++ = *sfn) if (!isalnum(*sfn)) break; else ++sfn; *--tp = 0; /* Just in case */ strcpy(ts, getenv(ts)); /* MARGINAL!! */ } /* If have leading ~, then expand login name (null means $HOME) */ else if (*sfn == '~') { ++sfn; if (*sfn == '/' || *sfn == 0) strcpy(ts, getenv("HOME")); else { tp = ts; while (*sfn && *sfn != '/') *tp++ = *sfn++; *tp = 0; pw = (struct passwd *)getpwnam(ts); if (! pw) strcpy(ts, "???"); else strcpy(ts, pw->pw_dir); } } /* Now, ts is either empty or contains the expansion; * sfn has been updated correctly. */ strcpy(dfn, ts); strcat(dfn, sfn);}#endif /*IMAGEN*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -