📄 proc.c
字号:
}#endif /* SPELL */voidShToBuf(){ char bnm[128], cmd[LBSIZE]; strcpy(bnm, ask((char *)NULL, "Buffer: ")); strcpy(cmd, ask(ShcomBuf, "Command: ")); DoShell(bnm, cmd);}voidShellCom(){ null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1); DoShell(MakeName(ShcomBuf), ShcomBuf);}voidShNoBuf(){ int status; null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1); status = UnixToBuf((char *)NULL, (char *)NULL, NO, 0, NO, Shell, ShFlags, ShcomBuf, curbuf->b_fname, curbuf->b_fname, (char *)NULL); com_finish(status, ShcomBuf);}voidShtypeout(){ int status; null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1); status = UnixToBuf((char *)NULL, (char *)NULL, YES, 0, NO, Shell, ShFlags, ShcomBuf, curbuf->b_fname, curbuf->b_fname, (char *)NULL); if (status == 0) Typeout("[%s: completed successfully]", ShcomBuf); else Typeout("[%s: exited (%d)]", ShcomBuf, status); TOstop();}/* Run the shell command into `bnm'. Empty the buffer except when we give a numeric argument, in which case it inserts the output at the current position in the buffer. */private voidDoShell(bnm, command)char *bnm, *command;{ Window *savewp = curwind; int status; char *fn = pr_name(curbuf->b_fname, NO); /* Two copies of the file name are passed to the shell: * The Cshell uses the first as a definition of $1 * Most version of the Bourne shell use the second as a definition of $1. */ status = UnixToBuf(bnm, (char *)NULL, YES, 0, !is_an_arg(), Shell, ShFlags, command, fn, fn, (char *)NULL); com_finish(status, command); SetWind(savewp);}private voidcom_finish(status, cmd)int status;char *cmd;{ s_mess("[%s: ", cmd); if (status == 0) add_mess("completed successfully"); else add_mess("exited (%d)", status); add_mess("]");}#ifndef MSDOSvoiddowait(pid, status)int pid, *status;{# ifndef IPROCS int rpid; do ; while ((rpid = wait(status)) != pid);# else# include "wait.h" union wait w; int rpid; for (;;) {# ifndef WAIT3 rpid = wait2(&w.w_status, 0);# else rpid = wait3(&w, 0, (struct rusage *)NULL);# endif if (rpid == -1) break; else if (rpid == pid) { if (status) *status = w.w_status; break; } else kill_off(rpid, w); }# endif /* IPROCS */}#endif /* MSDOS *//* Run the command to bnm, erase the buffer if clobber is non-zero, and redisplay if disp is non-zero. Leaves current buffer in `bnm' and leaves any windows it creates lying around. It's up to the caller to fix everything up after we're done. (Usually there's nothing to fix up.) */#ifdef STDARGSintUnixToBuf(char *bnm, char *InFName, bool disp, int wsize, bool clobber, ...)#else/*VARARGS5*/ intUnixToBuf(bnm, InFName, disp, wsize, clobber, va_alist) char *bnm, *InFName; bool disp; int wsize; bool clobber; va_dcl#endif{#ifndef MSDOS int p[2], pid;#else /* MSDOS */ char pnbuf[FILESIZE]; char *pipename;#endif /* MSDOS */ int status; bool eof; va_list ap; char *argv[32], *mess; File *fp; SIGRESULT (*old_int) proto((int)); va_init(ap, clobber); make_argv(argv, ap); va_end(ap); if (bnm != NULL && clobber == YES) isprocbuf(bnm); if (access(argv[0], X_OK) != 0) { complain("[Couldn't access %s: %s]", argv[0], strerror(errno)); /* NOTREACHED */ } if (disp) { if (bnm != NULL) { message("Starting up..."); pop_wind(bnm, clobber, clobber ? B_PROCESS : B_FILE); set_wsize(wsize); redisplay(); } else { TOstart(argv[0], TRUE); Typeout("Starting up..."); } } /* Now I will attempt to describe how I deal with signals during the execution of the shell command. My desire was to be able to interrupt the shell command AS SOON AS the window pops up. So, if we have BSD_SIGS (i.e., the new signal mechanism) I hold SIGINT, meaning if we interrupt now, we will eventually see the interrupt, but not before we are ready for it. We fork, the child releases the interrupt, it then sees the interrupt, and so exits. Meanwhile the parent ignores the signal, so if there was a pending one, it's now lost. With no BSD_SIGS, the best behavior you can expect is, when you type ^] too very quickly after the window pops up, it may be ignored. The behavior BEFORE was that it would interrupt JOVE and then you would have to continue JOVE and wait a little while longer before trying again. Now that is fixed, in that you just have to type it twice. */#ifndef MSDOS# ifdef IPROCS SigHold(SIGCHLD);# endif# ifdef BSD_SIGS SigHold(SIGINT);# else old_int = signal(SIGINT, SIG_IGN),# endif dopipe(p);#ifdef VFORK pid = vfork();#else pid = fork();#endif if (pid == -1) { pipeclose(p); complain("[Fork failed: %s]", strerror(errno)); } if (pid == 0) {# ifdef VFORK /* * We want to release SIGCHLD and SIGINT in the child, * but we can't use SigRelse because that would change * Jove's copy of the SigMask variable (because we're in * a vfork). So we simply set set the mask directly. * There are several other forks in Jove, but this is * the only one we execute often enough to make it worth * using a vfork. This assumes a system with vfork also * has BSD signals! */ (void) signal(SIGINT, SIG_DFL); (void) sigsetmask(SigMask & ~(sigmask(SIGCHLD)|sigmask(SIGINT)));# else /* !VFORK */# ifdef IPROCS SigRelse(SIGCHLD); /* don't know if this matters */# endif /* IPROCS */ (void) signal(SIGINT, SIG_DFL);# ifdef BSD_SIGS SigRelse(SIGINT);# endif /* BSD_SIGS */# endif /* !VFORK */ (void) close(0); (void) open(InFName==NULL? "/dev/null" : InFName, 0); (void) close(1); (void) close(2); (void) dup(p[1]); (void) dup(p[1]); pipeclose(p); jcloseall(); execv(argv[0], (const char **) &argv[1]); raw_complain("Execl failed: %s\n", strerror(errno)); _exit(1); }# ifdef BSD_SIGS old_int = signal(SIGINT, SIG_IGN);# endif (void) close(p[1]); fp = fd_open(argv[1], F_READ, p[0], iobuff, LBSIZE);#else /* MSDOS */ { int oldi = dup(0), oldo = dup(1), olde = dup(2); bool InFailure = FALSE; int ph; swritef(pnbuf, sizeof(pnbuf), "%s/%s", TmpFilePath, "jpXXXXXX"); pipename = mktemp(pnbuf); if ((ph = creat(pipename, S_IWRITE|S_IREAD)) < 0) complain("cannot make pipe for filter: %s", strerror(errno)); close(1); close(2); dup(ph); dup(ph); close(0); if (InFName == NULL) if (open(InFName, 0) < 0) InFailure = TRUE; if (!InFailure) status = spawnv(0, argv[0], &argv[1]); close(0); close(1); close(2); dup(oldi); dup(oldo); dup(olde); close(oldi); close(oldo); close(olde); if (InFailure) complain("[filter input failed]"); if (status < 0) complain("[Spawn failed]"); ph = open(pipename, 0); if (ph < 0) complain("[cannot reopen pipe]", strerror(errno)); fp = fd_open(argv[1], F_READ, ph, iobuff, LBSIZE); }#endif /* MSDOS */ do {#ifndef MSDOS inIOread = YES;#endif eof = f_gets(fp, genbuf, (size_t)LBSIZE);#ifndef MSDOS inIOread = NO;#endif if (bnm != NULL) { ins_str(genbuf, YES); if (!eof) LineInsert(1); } else if (disp) Typeout("%s", genbuf); if (bnm != NULL && disp && fp->f_cnt <= 0) {#ifdef LOAD_AV { int la = get_la(); if (la < 200) mess = "Screaming along..."; else if (la < 500) mess = "Chugging along..."; else mess = "Crawling along..."; }#else mess = "Chugging along...";#endif /* LOAD_AV */ if (bnm != NULL) { message(mess); redisplay(); } } } while (!eof); if (disp) DrawMesg(NO); close_file(fp);#ifndef MSDOS dowait(pid, &status);# ifdef BSD_SIGS (void) SigRelse(SIGINT);# endif# ifdef IPROCS SigRelse(SIGCHLD);# endif#else /* MSDOS */ unlink(pipename); getCWD();#endif /* MSDOS */ (void) signal(SIGINT, old_int); return status;}/* Send the current region to CMD and insert the output from the command into OUT_BUF. */private voidRegToUnix(outbuf, cmd)Buffer *outbuf;char *cmd;{ Mark *m = CurMark(); static char tnambuf[FILESIZE]; char *tname; Window *save_wind = curwind; volatile int status; volatile int err = NO; File *volatile fp; jmp_buf sav_jmp; swritef(tnambuf, sizeof(tnambuf), "%s/%s", TmpFilePath, "jfXXXXXX"); tname = mktemp(tnambuf); fp = open_file(tname, iobuff, F_WRITE, YES, YES); push_env(sav_jmp); if (setjmp(mainjmp) == 0) { putreg(fp, m->m_line, m->m_char, curline, curchar, YES); DelReg(); f_close(fp); status = UnixToBuf(outbuf->b_name, tname, NO, 0, outbuf->b_type==B_SCRATCH, Shell, ShFlags, cmd, (char *)NULL); } else { f_close(fp); err = YES; } pop_env(sav_jmp); (void) unlink(tname); SetWind(save_wind); if (!err) com_finish(status, cmd);}voidFilterRegion(){ static char FltComBuf[LBSIZE]; null_ncpy(FltComBuf, ask(FltComBuf, ": %f (through command) "), (sizeof FltComBuf) - 1); RegToUnix(curbuf, FltComBuf);}voidisprocbuf(bnm)char *bnm;{ Buffer *bp; if ((bp = buf_exists(bnm)) != NULL && bp->b_type != B_PROCESS) confirm("Over-write buffer %s? ", bnm);}#ifdef MSDOS/* ??? how many of these includes are redundant? Are they needed in RegToUnix()? */#include <dos.h>#include <fcntl.h>/* ??? Set the DOS path separator character to '/' from '\\' */charswitchar(){ union REGS regs; regs.h.ah = 0x37; regs.h.al = 0; intdos(®s, ®s); return regs.h.dl;}#endif /* MSDOS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -