|
|
1.1 root 1: /***************************************************************************
2: * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
3: * is provided to you without charge, and with no warranty. You may give *
4: * away copies of JOVE, including sources, provided that this notice is *
5: * included in all the files. *
6: ***************************************************************************/
7:
8: #include "jove.h"
9: #include "ctype.h"
10: #include "fp.h"
11: #include "re.h"
12: #include "termcap.h"
13: #include "disp.h"
14:
15: #include <signal.h>
16: #ifdef STDARGS
17: # include <stdarg.h>
18: #else
19: # include <varargs.h>
20: #endif
21:
22: #ifdef MSDOS
23: # include <io.h>
24: # include <process.h>
25: #endif
26:
27: private void
28: DoShell proto((char *, char *)),
29: com_finish proto((int, char *)),
30: toerror proto((int, int));
31:
32: #ifdef MSDOS
33: private void
34: closepipe proto((void));
35: #endif
36:
37: private int
38: okay_error proto((void));
39:
40: #if defined(MSDOS)
41: private int
42: openforpipe proto((void)),
43: reopenforpipe proto((void));
44: #endif
45:
46: private struct error
47: *AddError proto((struct error *, Line *, Buffer *, Line *, int));
48:
49: long SigMask = 0;
50:
51: /* This disgusting RE search string parses output from the GREP
52: family, from the pdp11 compiler, pcc, and lint. Jay (HACK)
53: Fenlasen changed this to work for the lint errors. */
54: char ErrFmtStr[256] = "^\\{\",\\}\\([^:\"( \t]*\\)\\{\"\\, line ,:,(\\} *\\([0-9][0-9]*\\)[:)]\
55: \\|:: *\\([^(]*\\)(\\([0-9]*\\))$\
56: \\|( \\([^(]*\\)(\\([0-9]*\\)) ),";
57:
58: struct error {
59: Buffer *er_buf; /* Buffer error is in */
60: Line *er_mess, /* Actual error message */
61: *er_text; /* Actual error */
62: int er_char; /* char pos of error */
63: struct error *er_prev, /* List of errors */
64: *er_next;
65: };
66:
67: private struct error *cur_error = NULL,
68: *errorlist = NULL;
69: Buffer *perr_buf = NULL; /* Buffer with error messages */
70:
71: int WtOnMk = 1; /* Write the modified files when we make */
72:
73: /* Add an error to the end of the list of errors. This is used for
74: parse-{C,LINT}-errors and for the spell-buffer command */
75:
76: private struct error *
77: AddError(laste, errline, buf, line, charpos)
78: struct error *laste;
79: Line *errline,
80: *line;
81: Buffer *buf;
82: int charpos;
83: {
84: struct error *new = (struct error *) emalloc(sizeof *new);
85:
86: new->er_prev = laste;
87: if (laste)
88: laste->er_next = new;
89: else {
90: if (errorlist) /* Free up old errors */
91: ErrFree();
92: cur_error = errorlist = new;
93: }
94: laste = new;
95: new->er_next = 0;
96: new->er_buf = buf;
97: new->er_text = line;
98: new->er_char = charpos;
99: new->er_mess = errline;
100:
101: return new;
102: }
103:
104: void
105: get_FL_info(fname, lineno)
106: char *fname,
107: *lineno;
108: {
109: putmatch(1, fname, (size_t)FILESIZE);
110: putmatch(2, lineno, (size_t)FILESIZE);
111:
112: /* error had lineno followed fname, so switch the two */
113: if (!isdigit(lineno[0])) {
114: char tmp[FILESIZE];
115:
116: strcpy(tmp, lineno);
117: strcpy(lineno, fname);
118: strcpy(fname, tmp);
119: }
120: }
121:
122: /* Free up all the errors */
123:
124: void
125: ErrFree()
126: {
127: register struct error *ep;
128:
129: for (ep = errorlist; ep != 0; ep = ep->er_next)
130: free((char *) ep);
131: errorlist = cur_error = 0;
132: }
133:
134: /* Parse errors of the form specified in ErrFmtStr in the current
135: buffer. Do a show error of the first error. This is neat because this
136: will work for any kind of output that prints a file name and a line
137: number on the same line. */
138:
139: void
140: ErrParse()
141: {
142: struct RE_block re_blk;
143: Bufpos *bp;
144: char fname[FILESIZE],
145: lineno[FILESIZE];
146: int lnum,
147: last_lnum = -1;
148: struct error *ep = 0;
149: Buffer *buf,
150: *lastb = 0;
151: Line *err_line;
152:
153: ErrFree(); /* This is important! */
154: ToFirst();
155: perr_buf = curbuf;
156: REcompile(ErrFmtStr, YES, &re_blk);
157: /* Find a line with a number on it. */
158: while ((bp = docompiled(FORWARD, &re_blk)) != NULL) {
159: SetDot(bp);
160: get_FL_info(fname, lineno);
161: buf = do_find((Window *) 0, fname, YES);
162: if (buf != lastb) {
163: lastb = buf;
164: last_lnum = -1; /* signals new file */
165: err_line = buf->b_first;
166: }
167: (void) chr_to_int(lineno, 10, NO, &lnum);
168: if (lnum == last_lnum) /* one error per line is nicer */
169: continue;
170: if (last_lnum == -1)
171: last_lnum = 1; /* that's where we really are */
172: err_line = next_line(err_line, lnum - last_lnum);
173: ep = AddError(ep, curline, buf, err_line, 0);
174: last_lnum = lnum;
175: }
176: if (cur_error != 0)
177: ShowErr();
178: }
179:
180: /* Internal next error sets cur_error to the next error, taking the
181: argument count, supplied by the user, into consideration. */
182:
183: private char errbounds[] = "You're at the %s error.",
184: noerrs[] = "No errors!";
185:
186: private void
187: toerror(forward, num)
188: int forward,
189: num;
190: {
191: register struct error *e = cur_error;
192:
193: if (e == 0)
194: complain(noerrs);
195: if ((forward && (e->er_next == 0)) ||
196: (!forward && (e->er_prev == 0)))
197: complain(errbounds, forward ? "last" : "first");
198:
199: while (--num >= 0) {
200: if ((e = forward ? e->er_next : e->er_prev) == 0)
201: break;
202: cur_error = e;
203: }
204: }
205:
206: void
207: NextError()
208: {
209: ToError(1);
210: }
211:
212: void
213: PrevError()
214: {
215: ToError(0);
216: }
217:
218: private int
219: okay_error()
220: {
221: return ((inlist(perr_buf->b_first, cur_error->er_mess)) &&
222: (inlist(cur_error->er_buf->b_first, cur_error->er_text)));
223: }
224:
225: /* Go the the next error, if there is one. Put the error buffer in
226: one window and the buffer with the error in another window.
227: It checks to make sure that the error actually exists. */
228:
229: void
230: ToError(forward)
231: int forward;
232: {
233: do {
234: toerror(forward, arg_value());
235: } while (!okay_error());
236: ShowErr();
237: }
238:
239: int EWSize = 20; /* percentage of screen the error window
240: should be */
241:
242: private void
243: set_wsize(wsize)
244: int wsize;
245: {
246: wsize = (LI * wsize) / 100;
247: if (wsize >= 1 && !one_windp())
248: WindSize(curwind, wsize - (curwind->w_height - 1));
249: }
250:
251: /* Show the current error, i.e. put the line containing the error message
252: in one window, and the buffer containing the actual error in another
253: window. */
254:
255: void
256: ShowErr()
257: {
258: Window *err_wind,
259: *buf_wind;
260:
261: if (cur_error == 0)
262: complain(noerrs);
263: if (!okay_error()) {
264: rbell();
265: return;
266: }
267: err_wind = windbp(perr_buf);
268: buf_wind = windbp(cur_error->er_buf);
269:
270: if (err_wind && !buf_wind) {
271: SetWind(err_wind);
272: pop_wind(cur_error->er_buf->b_name, NO, -1);
273: buf_wind = curwind;
274: } else if (!err_wind && buf_wind) {
275: SetWind(buf_wind);
276: pop_wind(perr_buf->b_name, NO, -1);
277: err_wind = curwind;
278: } else if (!err_wind && !buf_wind) {
279: pop_wind(perr_buf->b_name, NO, -1);
280: err_wind = curwind;
281: pop_wind(cur_error->er_buf->b_name, NO, -1);
282: buf_wind = curwind;
283: }
284:
285: /* Put the current error message at the top of its Window */
286: SetWind(err_wind);
287: SetLine(cur_error->er_mess);
288: SetTop(curwind, (curwind->w_line = cur_error->er_mess));
289: set_wsize(EWSize);
290:
291: /* now go to the the line with the error in the other window */
292: SetWind(buf_wind);
293: DotTo(cur_error->er_text, cur_error->er_char);
294: }
295:
296: char ShcomBuf[LBSIZE];
297:
298: /* Make a buffer name given the command `command', i.e. "fgrep -n foo *.c"
299: will return the buffer name "fgrep". */
300:
301: char *
302: MakeName(command)
303: char *command;
304: {
305: static char bnm[50];
306: register char *cp = bnm,
307: c;
308:
309: while ((c = *command++) != '\0' && (c == ' ' || c == '\t'))
310: ;
311: do
312: *cp++ = c;
313: while ((c = *command++) != '\0' && (c != ' ' && c != '\t'));
314: *cp = 0;
315: strcpy(bnm, basename(bnm));
316:
317: return bnm;
318: }
319:
320: /* Run make, first writing all the modified buffers (if the WtOnMk flag is
321: non-zero), parse the errors, and go the first error. */
322:
323: private char make_cmd[LBSIZE] = "make";
324:
325: void
326: MakeErrors()
327: {
328: Window *old = curwind;
329: int status,
330: compilation;
331:
332: if (WtOnMk)
333: put_bufs(0);
334: /* When we're not doing make or cc (i.e., the last command
335: was probably a grep or something) and the user just types
336: C-X C-E, he probably (possibly, hopefully, usually (in my
337: case)) doesn't want to do the grep again but rather wants
338: to do a make again; so we ring the bell and insert the
339: default command and let the person decide. */
340:
341: compilation = (sindex("make", make_cmd) || sindex("cc", make_cmd));
342: if (is_an_arg() || !compilation) {
343: if (!compilation) {
344: rbell();
345: Inputp = make_cmd; /* insert the default for the user */
346: }
347: null_ncpy(make_cmd, ask(make_cmd, "Compilation command: "),
348: sizeof (make_cmd) - 1);
349: }
350: status = UnixToBuf(MakeName(make_cmd), YES, EWSize, YES, Shell, ShFlags, make_cmd, (char *) 0);
351: com_finish(status, make_cmd);
352:
353: ErrParse();
354:
355: if (!cur_error)
356: SetWind(old);
357: }
358:
359: #ifdef SPELL
360:
361: private void
362: SpelParse(bname)
363: char *bname;
364: {
365: Buffer *buftospel,
366: *wordsb;
367: char wordspel[100];
368: Bufpos *bp;
369: struct error *ep = 0;
370:
371: ErrFree(); /* This is important! */
372:
373: buftospel = curbuf;
374: wordsb = buf_exists(bname);
375: perr_buf = wordsb; /* This is important (buffer containing
376: error messages) */
377: SetBuf(wordsb);
378: ToFirst();
379: f_mess("Finding misspelled words ... ");
380: while (!lastp(curline)) {
381: swritef(wordspel, "\\<%s\\>", linebuf);
382: SetBuf(buftospel);
383: ToFirst();
384: while ((bp = dosearch(wordspel, 1, 1)) != NULL) {
385: SetDot(bp);
386: ep = AddError(ep, wordsb->b_dot, buftospel,
387: curline, curchar);
388: }
389: SetBuf(wordsb);
390: line_move(FORWARD, 1, NO);
391: }
392: add_mess("Done.");
393: SetBuf(buftospel);
394: ShowErr();
395: }
396:
397: void
398: SpelBuffer()
399: {
400: char *Spell = "Spell",
401: com[100];
402: Window *savewp = curwind;
403:
404: put_bufs(0);
405: swritef(com, "spell %s", curbuf->b_fname);
406: (void) UnixToBuf(Spell, YES, EWSize, YES, Shell, ShFlags, com, (char *) 0);
407: message("[Delete the irrelevant words and then type C-X C-C]");
408: ToFirst();
409: Recur();
410: SetWind(savewp);
411: SpelParse(Spell);
412: }
413:
414: void
415: SpelWords()
416: {
417: char *buftospel;
418: Buffer *wordsb = curbuf;
419:
420: if ((buftospel = ask_buf((Buffer *) 0)) == 0)
421: return;
422: SetBuf(do_select(curwind, buftospel));
423: SpelParse(wordsb->b_name);
424: }
425:
426: #endif /* SPELL */
427:
428: void
429: ShToBuf()
430: {
431: char bnm[128],
432: cmd[128];
433:
434: strcpy(bnm, ask((char *) 0, "Buffer: "));
435: strcpy(cmd, ask(ShcomBuf, "Command: "));
436: DoShell(bnm, cmd);
437: }
438:
439: void
440: ShellCom()
441: {
442: null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1);
443: DoShell(MakeName(ShcomBuf), ShcomBuf);
444: }
445:
446: void
447: ShNoBuf()
448: {
449: int status;
450:
451: null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1);
452: status = UnixToBuf((char *) 0, NO, 0, NO, Shell, ShFlags, ShcomBuf,
453: curbuf->b_fname, curbuf->b_fname, (char *) 0);
454: com_finish(status, ShcomBuf);
455: }
456:
457: void
458: Shtypeout()
459: {
460: int status;
461:
462: null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1);
463: status = UnixToBuf((char *) 0, YES, 0, NO, Shell, ShFlags, ShcomBuf,
464: curbuf->b_fname, curbuf->b_fname, (char *) 0);
465: if (status == 0)
466: Typeout("[%s: completed successfully]", ShcomBuf);
467: else
468: Typeout("[%s: exited (%d)]", ShcomBuf, status);
469: TOstop();
470: }
471:
472: /* Run the shell command into `bnm'. Empty the buffer except when we
473: give a numeric argument, in which case it inserts the output at the
474: current position in the buffer. */
475:
476: private void
477: DoShell(bnm, command)
478: char *bnm,
479: *command;
480: {
481: Window *savewp = curwind;
482: int status;
483:
484: status = UnixToBuf(bnm, YES, 0, !is_an_arg(), Shell, ShFlags,
485: command, curbuf->b_fname, curbuf->b_fname, (char *) 0);
486: com_finish(status, command);
487: SetWind(savewp);
488: }
489:
490: private void
491: com_finish(status, cmd)
492: int status;
493: char *cmd;
494: {
495: s_mess("[%s: ", cmd);
496: if (status == 0)
497: add_mess("completed successfully");
498: else
499: add_mess("exited (%d)", status);
500: add_mess("]");
501: }
502:
503: #ifndef MSDOS
504: void
505: dowait(pid, status)
506: int pid,
507: *status;
508: {
509: # ifndef IPROCS
510:
511: int rpid;
512:
513: while ((rpid = wait(status)) != pid)
514: ;
515: # else
516:
517: # include "wait.h"
518:
519: union wait w;
520: int rpid;
521:
522: for (;;) {
523: # ifndef WAIT3
524: rpid = wait2(&w.w_status, 0);
525: # else
526: rpid = wait3(&w, 0, (struct rusage *) 0);
527: # endif
528: if (rpid == -1)
529: break;
530: else if (rpid == pid) {
531: if (status)
532: *status = w.w_status;
533: break;
534: } else
535: kill_off(rpid, w);
536: }
537: # endif /* IPROCS */
538: }
539: #endif /* MSDOS */
540:
541: /* Run the command to bnm, erase the buffer if clobber is non-zero,
542: and redisplay if disp is non-zero. Leaves current buffer in `bnm'
543: and leaves any windows it creates lying around. It's up to the caller
544: to fix everything up after we're done. (Usually there's nothing to
545: fix up.) */
546:
547: #ifdef STDARGS
548: int
549: UnixToBuf(char *bnm, int disp, int wsize, int clobber, ...)
550: #else
551: /*VARARGS4*/ int
552: UnixToBuf(bnm, disp, wsize, clobber, va_alist)
553: char *bnm;
554: int disp;
555: int wsize;
556: int clobber;
557: va_dcl
558: #endif
559: {
560: #ifndef MSDOS
561: int p[2],
562: pid,
563: status,
564: #else /* MSDOS */
565: int p0,
566: oldo,
567: olde,
568: retcode,
569: #endif /* MSDOS */
570: eof;
571: va_list ap;
572: char *argv[32],
573: *mess;
574: File *fp;
575: SIGRESULT (*old_int) proto((int));
576:
577: va_init(ap, clobber);
578: make_argv(argv, ap);
579: va_end(ap);
580: if (bnm != 0 && clobber == YES)
581: isprocbuf(bnm);
582: if (disp) {
583: if (bnm != 0)
584: message("Starting up...");
585: else {
586: TOstart(argv[0], TRUE);
587: Typeout("Starting up...");
588: }
589: if (bnm != 0) {
590: pop_wind(bnm, clobber, clobber ? B_PROCESS : B_FILE);
591: set_wsize(wsize);
592: redisplay();
593: }
594: }
595: /* Now I will attempt to describe how I deal with signals during
596: the execution of the shell command. My desire was to be able
597: to interrupt the shell command AS SOON AS the window pops up.
598: So, if we have JOB_CONTROL (i.e., the new signal mechanism) I
599: hold SIGINT, meaning if we interrupt now, we will eventually
600: see the interrupt, but not before we are ready for it. We
601: fork, the child releases the interrupt, it then sees the
602: interrupt, and so exits. Meanwhile the parent ignores the
603: signal, so if there was a pending one, it's now lost.
604:
605: With no JOB_CONTROL, the best behavior you can expect is, when
606: you type ^] too very quickly after the window pops up, it may
607: be ignored. The behavior BEFORE was that it would interrupt
608: JOVE and then you would have to continue JOVE and wait a
609: little while longer before trying again. Now that is fixed,
610: in that you just have to type it twice. */
611:
612: #ifndef MSDOS
613: # ifdef IPROCS
614: SigHold(SIGCHLD);
615: # endif
616: # ifdef JOB_CONTROL
617: SigHold(SIGINT);
618: # else
619: old_int = signal(SIGINT, SIG_IGN),
620: # endif
621: dopipe(p);
622: pid = vfork();
623: if (pid == -1) {
624: pclose(p);
625: complain("[Fork failed]");
626: }
627: if (pid == 0) {
628: # ifdef BSD_SIGS
629: /*
630: * We want to release SIGCHLD and SIGINT in the child, but
631: * we can't use SigRelse because that would change Jove's
632: * copy of the SigMask variable (because we're in a
633: * vfork). So we simply set set the mask directly. There
634: * are several other forks in Jove, but this is the only
635: * one we execute often enough to make it worth using a
636: * vfork.
637: */
638: (void) signal(SIGINT, SIG_DFL);
639: (void) sigsetmask(SigMask & ~(sigmask(SIGCHLD)|sigmask(SIGINT)));
640: # else /* BSD_SIGS */
641: # ifdef IPROCS
642: SigRelse(SIGCHLD); /* don't know if this matters */
643: # endif /* IPROCS */
644: (void) signal(SIGINT, SIG_DFL);
645: # ifdef JOB_CONTROL
646: SigRelse(SIGINT);
647: # endif
648: # endif /* BSD_SIGS */
649: (void) close(0);
650: (void) open("/dev/null", 0);
651: (void) close(1);
652: (void) close(2);
653: (void) dup(p[1]);
654: (void) dup(p[1]);
655: pclose(p);
656: execv(argv[0], (const char **) &argv[1]);
657: (void) write(1, "Execl failed.\n", (size_t) 14);
658: _exit(1);
659: }
660: # ifdef JOB_CONTROL
661: old_int = signal(SIGINT, SIG_IGN);
662: # endif
663: (void) close(p[1]);
664: fp = fd_open(argv[1], F_READ, p[0], iobuff, LBSIZE);
665: #else /* MSDOS */
666: if ((p0 = openforpipe()) < 0)
667: complain("cannot make pipe for filter");
668:
669: oldo = dup(1);
670: olde = dup(2);
671: close(1);
672: close(2);
673: dup(p0);
674: dup(1);
675: close(p0);
676: retcode = spawnv(0, argv[0], &argv[1]);
677: p0 = reopenforpipe();
678: close(1);
679: close(2);
680: dup(oldo);
681: dup(olde);
682: close(oldo);
683: close(olde);
684:
685: if (retcode < 0)
686: complain("[Spawn failed]");
687:
688: fp = fd_open(argv[1], F_READ, p0, iobuff, LBSIZE);
689: #endif /* MSDOS */
690: do {
691: #ifndef MSDOS
692: inIOread = 1;
693: #endif
694: eof = f_gets(fp, genbuf, (size_t)LBSIZE);
695: #ifndef MSDOS
696: inIOread = 0;
697: #endif
698: if (bnm != 0) {
699: ins_str(genbuf, YES);
700: if (!eof)
701: LineInsert(1);
702: } else if (disp == YES)
703: Typeout("%s", genbuf);
704: if (bnm != 0 && disp != 0 && fp->f_cnt <= 0) {
705: #ifdef LOAD_AV
706: {
707: double theavg;
708:
709: get_la(&theavg);
710: if (theavg < 2.0)
711: mess = "Screaming along...";
712: else if (theavg < 5.0)
713: mess = "Chugging along...";
714: else
715: mess = "Crawling along...";
716: }
717: #else
718: mess = "Chugging along...";
719: #endif /* LOAD_AV */
720: if (bnm != 0) {
721: message(mess);
722: redisplay();
723: }
724: }
725: } while (!eof);
726: if (disp)
727: DrawMesg(NO);
728: close_file(fp);
729: #ifndef MSDOS
730: dowait(pid, &status);
731: # ifdef JOB_CONTROL
732: (void) SigRelse(SIGINT);
733: # endif
734: #else /* MSDOS */
735: closepipe();
736: #endif /* MSDOS */
737: (void) signal(SIGINT, old_int);
738: #ifndef MSDOS
739: # ifdef IPROCS
740: SigRelse(SIGCHLD);
741: # endif
742: return status;
743: #else /* MSDOS */
744: getCWD();
745: return retcode;
746: #endif /* MSDOS */
747: }
748:
749: /* Send the current region to CMD and insert the output from the
750: command into OUT_BUF. */
751:
752: void
753: RegToUnix(outbuf, cmd)
754: Buffer *outbuf;
755: char *cmd;
756: {
757: Mark *m = CurMark();
758: #ifndef MSDOS
759: static char tnambuf[20];
760: char *tname,
761: combuf[128];
762: #endif /* MSDOS */
763: Window *save_wind = curwind;
764: int status,
765: err = NO;
766: #ifdef MSDOS
767: int p0, oldi;
768: #endif /* MSDOS */
769: File *fp;
770:
771: #ifndef MSDOS
772: strcpy (tnambuf, "/tmp/jfilterXXXXXX");
773: tname = mktemp(tnambuf);
774: fp = open_file(tname, iobuff, F_WRITE, YES, YES);
775: #else /* MSDOS */
776: p0 = openforpipe();
777: #endif /* MSDOS */
778: CATCH
779: #ifdef MSDOS
780: fp = fd_open(cmd, F_WRITE, p0, iobuff, LBSIZE);
781: #endif /* MSDOS */
782: putreg(fp, m->m_line, m->m_char, curline, curchar, YES);
783: DelReg();
784: #ifndef MSDOS
785: swritef(combuf, "%s < %s", cmd, tname);
786: #else /* MSDOS */
787: f_close(fp);
788: p0 = reopenforpipe();
789: oldi = dup(0);
790: close(0);
791: dup(p0);
792: close(p0);
793: #endif /* MSDOS */
794: status = UnixToBuf(outbuf->b_name, NO, 0, outbuf->b_type == B_SCRATCH,
795: #ifndef MSDOS
796: Shell, ShFlags, combuf, (char *) 0
797: #else /* MSDOS */
798: Shell, ShFlags, cmd, (char *) 0
799: #endif /* MSDOS */
800: );
801: ONERROR
802: err = YES;
803: ENDCATCH
804: #ifndef MSDOS
805: f_close(fp);
806: (void) unlink(tname);
807: #else /* MSDOS */
808: close(0);
809: open("con", 0); /* dup(oldi); */
810: close(oldi);
811: closepipe();
812: #endif /* MSDOS */
813: SetWind(save_wind);
814: if (err == NO)
815: #ifndef MSDOS
816: com_finish(status, combuf);
817: #else
818: com_finish(status, cmd);
819: #endif
820: }
821:
822: void
823: FilterRegion()
824: {
825: static char FltComBuf[LBSIZE];
826:
827: null_ncpy(FltComBuf, ask(FltComBuf, ": %f (through command) "),
828: (sizeof FltComBuf) - 1);
829: RegToUnix(curbuf, FltComBuf);
830: }
831:
832: void
833: isprocbuf(bnm)
834: char *bnm;
835: {
836: Buffer *bp;
837:
838: if ((bp = buf_exists(bnm)) != 0 && bp->b_type != B_PROCESS)
839: confirm("Over-write buffer %s?", bnm);
840: }
841:
842: #ifdef MSDOS
843: /* msdos specific hacks to allow for pipes */
844:
845: #include <dos.h>
846: #include <fcntl.h>
847: #include <sys/stat.h>
848:
849: static char pipeiname[64];
850: static char pipeoname[64];
851: static int pipehandle;
852:
853: private int
854: openforpipe()
855: {
856: swritef(pipeiname, "%s/%s", TmpFilePath, "Jove-I");
857: swritef(pipeoname, "%s/%s", TmpFilePath, "Jove-O");
858:
859: return(pipehandle = creat(pipeoname, S_IWRITE|S_IREAD));
860: }
861:
862: private int
863: reopenforpipe()
864: {
865: close(pipehandle);
866: unlink(pipeiname);
867: rename(pipeoname, pipeiname);
868: if ((pipehandle = open(pipeiname, 0)) >= 0)
869: return(pipehandle);
870: closepipe();
871: return(-1);
872: }
873:
874: private void
875: closepipe()
876: {
877: unlink(pipeoname);
878: unlink(pipeiname);
879: }
880:
881: char
882: switchar()
883: {
884: union REGS regs;
885:
886: regs.h.ah = 0x37;
887: regs.h.al = 0;
888: intdos(®s, ®s);
889: return(regs.h.dl);
890: }
891: #endif /* MSDOS */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.