📄 b.c
字号:
unsigned char *canonical(unsigned char *n){#ifndef __MSDOS__ int x; unsigned char *s; if (n[0] == '~') { for (x = 1; n[x] && n[x] != '/'; ++x) ; if (n[x] == '/') { if (x == 1) { unsigned char *z; s = (unsigned char *)getenv("HOME"); z = vsncpy(NULL, 0, sz(s)); z = vsncpy(z, sLEN(z), sz(n + x)); vsrm(n); n = z; } else { struct passwd *passwd; n[x] = 0; passwd = getpwnam((char *)(n + 1)); n[x] = '/'; if (passwd) { unsigned char *z = vsncpy(NULL, 0, sz((unsigned char *)(passwd->pw_dir))); z = vsncpy(z, sLEN(z), sz(n + x)); vsrm(n); n = z; } } } }#endif return n;}/* Load file into new buffer and return the new buffer *//* Returns with error set to 0 for success, * -1 for new file (file doesn't exist) * -2 for read error * -3 for seek error * -4 for open error */B *bload(unsigned char *s){ unsigned char buffer[SEGSIZ]; FILE *fi = 0; B *b = 0; off_t skip, amnt; unsigned char *n; int nowrite = 0; P *p; int x; long mod_time = 0; struct stat sbuf; if (!s || !s[0]) { berror = -1; b = bmk(NULL); setopt(b,USTR ""); b->rdonly = b->o.readonly; b->er = berror; return b; } n = parsens(s, &skip, &amnt); /* Open file or stream */#ifndef __MSDOS__ if (n[0] == '!') { nescape(maint->t); ttclsn(); fi = popen((char *)(n + 1), "r"); } else#endif if (!zcmp(n, USTR "-")) {#ifdef junk FILE *f; struct stat y; fi = stdin; /* Make sure stdin is not tty */ if (fstat(fileno(fi), &y)) goto no_stat; if (y.st_mode & S_IFCHR) { no_stat: b = bmk(NULL); goto empty; }#endif /* Now we always just create an empty buffer for "-" */ b = bmk(NULL); goto empty; } else { fi = fopen((char *)n, "r+"); if (!fi) nowrite = 1; else fclose(fi); fi = fopen((char *)n, "r"); if (!fi) nowrite = 0; if (fi) { fstat(fileno(fi),&sbuf); mod_time = sbuf.st_mtime; } } joesep(n); /* Abort if couldn't open */ if (!fi) { if (errno == ENOENT) berror = -1; else berror = -4; b = bmk(NULL); setopt(b,n); b->rdonly = b->o.readonly; goto opnerr; } /* Skip data if we need to */ if (skip && lseek(fileno(fi), skip, 0) < 0) { int r; while (skip > SEGSIZ) { r = bkread(fileno(fi), buffer, SEGSIZ); if (r != SEGSIZ || berror) { berror = -3; goto err; } skip -= SEGSIZ; } skip -= bkread(fileno(fi), buffer, (int) skip); if (skip || berror) { berror = -3; goto err; } } /* Read from stream into new buffer */ b = bread(fileno(fi), amnt); empty: b->mod_time = mod_time; setopt(b,n); b->rdonly = b->o.readonly; /* Close stream */err:#ifndef __MSDOS__ if (s[0] == '!') pclose(fi); else#endif if (zcmp(n, USTR "-")) fclose(fi);opnerr: if (s[0] == '!') { ttopnn(); nreturn(maint->t); } /* Set name */ b->name = joesep(zdup(s)); /* Set flags */ if (berror || s[0] == '!' || skip || amnt != MAXLONG) { b->backup = 1; b->changed = 0; } else if (!zcmp(n, USTR "-")) { b->backup = 1; b->changed = 1; } else { b->backup = 0; b->changed = 0; } if (nowrite) b->rdonly = b->o.readonly = 1; /* If first line has CR-LF, assume MS-DOS file */ if (guesscrlf) { p=pdup(b->bof, USTR "bload"); b->o.crlf = 0; for(x=0;x!=1024;++x) { int c = pgetc(p); if(c == '\r') { b->o.crlf = 1; break; } if(c == '\n') { b->o.crlf = 0; break; } if(c == NO_MORE_DATA) break; } prm(p); } /* Search backwards through file: if first indented line is indented with a tab, assume indentc is tab */ if (guessindent) { p=pdup(b->eof, USTR "bload"); for (x=0; x!=20; ++x) { p_goto_bol(p); if (pisindent(p)) { if (brc(p)=='\t') { b->o.indentc = '\t'; b->o.istep = 1; } else { b->o.indentc = ' '; b->o.istep = 2; } break; } if (prgetc(p)==NO_MORE_DATA) break; } prm(p); } /* Eliminate parsed name */ vsrm(n); b->er = berror; return b;}/* Find already loaded buffer or load file into new buffer */B *bfind(unsigned char *s){ B *b; if (!s || !s[0]) { berror = -1; b = bmk(NULL); setopt(b,USTR ""); b->rdonly = b->o.readonly; b->internal = 0; b->er = berror; return b; } for (b = bufs.link.next; b != &bufs; b = b->link.next) if (b->name && !zcmp(s, b->name)) { if (!b->orphan) ++b->count; /* Assumes caller is going to put this in a window! */ else b->orphan = 0; berror = 0; b->internal = 0; return b; } b = bload(s); /* Returns count==1 */ b->internal = 0; return b;}/* Find already loaded buffer or load file into new buffer */B *bfind_scratch(unsigned char *s){ B *b; if (!s || !s[0]) { berror = -1; b = bmk(NULL); setopt(b,USTR ""); b->rdonly = b->o.readonly; b->internal = 0; b->er = berror; return b; } for (b = bufs.link.next; b != &bufs; b = b->link.next) if (b->name && !zcmp(s, b->name)) { if (!b->orphan) ++b->count; else b->orphan = 0; berror = 0; b->internal = 0; return b; } b = bmk(NULL); berror = -1; setopt(b,s); b->internal = 0; b->rdonly = b->o.readonly; b->er = berror; b->name = zdup(s); b->scratch = 1; return b;}B *bfind_reload(unsigned char *s){ B *b; b = bload(s); b->internal = 0; return b;}B *bcheck_loaded(unsigned char *s){ B *b; if (!s || !s[0]) { return NULL; } for (b = bufs.link.next; b != &bufs; b = b->link.next) if (b->name && !zcmp(s, b->name)) { return b; } return NULL;}unsigned char **getbufs(void){ unsigned char **s = vamk(16); B *b; for (b = bufs.link.next; b != &bufs; b = b->link.next) if (b->name) s = vaadd(s, vsncpy(NULL, 0, sz(b->name))); return s;}/* Find an orphaned buffer: b->count of returned buffer should be 1. */B *borphan(void){ B *b; for (b = bufs.link.next; b != &bufs; b = b->link.next) if (b->orphan && !b->scratch) { b->orphan = 0; return b; } return NULL;}/* Write 'size' bytes from file beginning at 'p' to open file 'fd'. * Returns error. * error is set to -5 for write error or 0 for success. * Don't attempt to write past the end of the file */int bsavefd(P *p, int fd, off_t size){ P *np = pdup(p, USTR "bsavefd"); int amnt; while (size > (amnt = GSIZE(np->hdr) - np->ofst)) { if (np->ofst < np->hdr->hole) { if (joe_write(fd, np->ptr + np->ofst, np->hdr->hole - np->ofst) < 0) goto err; if (joe_write(fd, np->ptr + np->hdr->ehole, SEGSIZ - np->hdr->ehole) < 0) goto err; } else if (joe_write(fd, np->ptr + np->ofst + GGAPSZ(np->hdr), amnt) < 0) goto err; size -= amnt; pnext(np); } if (size) { if (np->ofst < np->hdr->hole) { if (size > np->hdr->hole - np->ofst) { if (joe_write(fd, np->ptr + np->ofst, np->hdr->hole - np->ofst) < 0) goto err; if (joe_write(fd, np->ptr + np->hdr->ehole, (int) size - np->hdr->hole + np->ofst) < 0) goto err; } else { if (joe_write(fd, np->ptr + np->ofst, (int) size) < 0) goto err; } } else { if (joe_write(fd, np->ptr + np->ofst + GGAPSZ(np->hdr), (int) size) < 0) goto err; } } prm(np); return berror = 0;err: prm(np); return berror = 5;}/* Save 'size' bytes beginning at 'p' in file 's' *//* If flag is set, update original time of file if it makes * sense to do so (it's a normal file, we're saving with * same name as buffer or is about to get this name). */int break_links; /* Set to break hard links on writes */int bsave(P *p, unsigned char *s, off_t size, int flag){ FILE *f; off_t skip, amnt; struct stat sbuf; int norm = 0; s = parsens(s, &skip, &amnt); if (amnt < size) size = amnt;#ifndef __MSDOS__ if (s[0] == '!') { nescape(maint->t); ttclsn(); f = popen((char *)(s + 1), "w"); } else#endif if (s[0] == '>' && s[1] == '>') f = fopen((char *)(s + 2), "a"); else if (!zcmp(s, USTR "-")) { nescape(maint->t); ttclsn(); f = stdout; } else if (skip || amnt != MAXLONG) f = fopen((char *)s, "r+"); else { /* Normal file save */ if (break_links) { struct stat sbuf; /* Try to copy permissions */ if (!stat((char *)s,&sbuf)) { int g;#ifdef WITH_SELINUX security_context_t se; if (selinux_enabled == -1) selinux_enabled = (is_selinux_enabled() > 0); if (selinux_enabled) { if (getfilecon((char *)s, &se) < 0) { berror = -4; goto opnerr; } }#endif unlink((char *)s); g = creat((char *)s, sbuf.st_mode & ~(S_ISUID | S_ISGID));#ifdef WITH_SELINUX if (selinux_enabled) { setfilecon((char *)s, &se); freecon(se); }#endif close(g); } else { unlink((char *)s); } } f = fopen((char *)s, "w"); norm = 1; } joesep(s); if (!f) { berror = -4; goto opnerr; } fflush(f); if (skip && lseek(fileno(f), skip, 0) < 0) { berror = -3; goto err; } bsavefd(p, fileno(f), size); if (!berror && force && size && !skip && amnt == MAXLONG) { P *q = pdup(p, USTR "bsave"); unsigned char nl = '\n'; pfwrd(q, size - 1); if (brc(q) != '\n' && joe_write(fileno(f), &nl, 1) < 0) berror = -5; prm(q); }err:#ifndef __MSDOS__ if (s[0] == '!') pclose(f); else#endif if (zcmp(s, USTR "-")) fclose(f); else fflush(f); /* Update orignal date of file */ /* If it's not named, it's about to be */ if (!berror && norm && flag && (!p->b->name || !zcmp(s,p->b->name))) { if (!stat((char *)s,&sbuf)) p->b->mod_time = sbuf.st_mtime; }opnerr: if (s[0] == '!' || !zcmp(s,USTR "-")) { ttopnn(); nreturn(maint->t); } return berror;}/* Return byte at p */int brc(P *p){ if (p->ofst == GSIZE(p->hdr)) return NO_MORE_DATA; return GCHAR(p);}/* Return character at p */int brch(P *p){ if (p->b->o.charmap->type) { P *q = pdup(p, USTR "brch"); int c = pgetc(q); prm(q); return c; } else { return brc(p); }}unsigned char *brmem(P *p, unsigned char *blk, int size){ unsigned char *bk = blk; P *np; int amnt; np = pdup(p, USTR "brmem"); while (size > (amnt = GSIZE(np->hdr) - np->ofst)) { grmem(np->hdr, np->ptr, np->ofst, bk, amnt); bk += amnt; size -= amnt; pnext(np); } if (size) grmem(np->hdr, np->ptr, np->ofst, bk, size); prm(np); return blk;}unsigned char *brs(P *p, int size){ unsigned char *s = (unsigned char *) joe_malloc(size + 1); s[size] = 0; return brmem(p, s, size);}unsigned char *brvs(P *p, int size){ unsigned char *s = vstrunc(NULL, size); return brmem(p, (unsigned char *)s, size);}unsigned char *brzs(P *p, unsigned char *buf, int size){ P *q=pdup(p, USTR "brzs"); p_goto_eol(q); if(q->byte-p->byte<size) size = q->byte - p->byte; prm(q); brmem(p,buf,size); buf[size]=0; return buf;}/* Save edit buffers when editor dies */RETSIGTYPE ttsig(int sig){ time_t tim = time(NULL); B *b; FILE *f; int tmpfd; struct stat sbuf; if ((tmpfd = open("DEADJOE", O_RDWR | O_EXCL | O_CREAT, 0600)) < 0) { if (lstat("DEADJOE", &sbuf) < 0) _exit(-1); if (!S_ISREG(sbuf.st_mode) || sbuf.st_uid != geteuid()) _exit(-1); /* A race condition still exists between the lstat() and the open() systemcall, which leads to a possible denial-of-service attack by setting the file access mode to 600 for every file the user executing joe has permissions to. This can't be fixed w/o breacking the behavior of the orig. joe! */ if ((tmpfd = open("DEADJOE", O_RDWR | O_APPEND)) < 0) _exit(-1); if (fchmod(tmpfd, S_IRUSR | S_IWUSR) < 0) _exit(-1); } if ((f = fdopen(tmpfd, "a")) == NULL) _exit(-1); fprintf(f, (char *)joe_gettext(_("\n*** These modified files were found in JOE when it aborted on %s")), ctime(&tim)); if (sig) fprintf(f, (char *)joe_gettext(_("*** JOE was aborted by UNIX signal %d\n")), sig); else fprintf(f, (char *)joe_gettext(_("*** JOE was aborted because the terminal closed\n"))); fflush(f); for (b = bufs.link.next; b != &bufs; b = b->link.next) if (b->changed) { if (b->name) fprintf(f, (char *)joe_gettext(_("\n*** File \'%s\'\n")), b->name); else fprintf(f, (char *)joe_gettext(_("\n*** File \'(Unnamed)\'\n"))); fflush(f); bsavefd(b->bof, fileno(f), b->eof->byte); } if (sig) ttclsn(); _exit(1);}/* Create lock for a file Return 0 for success or -1 for failure*/int lock_it(unsigned char *path,unsigned char *bf){ unsigned char *lock_name=dirprt(path); unsigned char *name=namprt(path); unsigned char buf[1024]; unsigned char *user = (unsigned char *)getenv("USER"); unsigned char *host = (unsigned char *)getenv("HOSTNAME"); int len; if (!user) user=USTR "me"; if (!host) host=USTR "here"; lock_name=vsncpy(sv(lock_name),sc(".#")); lock_name=vsncpy(sv(lock_name),sv(name)); joe_snprintf_3(buf,sizeof(buf),"%s@%s.%d",user,host,getpid()); /* Fail only if there was an existing lock */ if (!symlink((char *)buf,(char *)lock_name) || errno != EEXIST) { vsrm(lock_name); vsrm(name); return 0; } if (bf) { len = readlink((char *)lock_name,(char *)bf,255); if (len<0) len = 0; bf[len] = 0; } vsrm(lock_name); vsrm(name); return -1;}void unlock_it(unsigned char *path){ unsigned char *lock_name=dirprt(path); unsigned char *name=namprt(path); lock_name=vsncpy(sv(lock_name),sc(".#")); lock_name=vsncpy(sv(lock_name),sv(name)); unlink((char *)lock_name); vsrm(lock_name); vsrm(name);}/* True if file is regular */int plain_file(B *b){ if (b->name && zcmp(b->name,USTR "-") && b->name[0]!='!' && b->name[0]!='>' && !b->scratch) return 1; else return 0;}/* True if file changed under us */int check_mod(B *b){ struct stat sbuf; if (!plain_file(b)) return 0; if (!stat((char *)b->name,&sbuf)) { if (sbuf.st_mtime>b->mod_time) { return 1; } } return 0;}/* True if file exists */int file_exists(unsigned char *path){ struct stat sbuf; if (!path) return 0; return !stat((char *)path, &sbuf);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -