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