|
|
1.1 root 1: /*
2: * Copyright (c) 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that this notice is preserved and that due credit is given
7: * to the University of California at Berkeley. The name of the University
8: * may not be used to endorse or promote products derived from this
9: * software without specific prior written permission. This software
10: * is provided ``as is'' without express or implied warranty.
11: */
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)sys_dos.c 1.3 (Berkeley) 3/8/88";
15: #endif /* not lint */
16:
17: #if defined(MSDOS)
18: #include <time.h>
19: #include <signal.h>
20: #include <process.h>
21: #include <fcntl.h>
22: #include <io.h>
23: #include <dos.h>
24: #include <ctype.h>
25:
26: #include "externs.h"
27: #include "defines.h"
28:
29: #if !defined(SO_OOBINLINE)
30: #define SO_OOBINLINE
31: #endif /* !defined(SO_OOBINLINE) */
32:
33:
34:
35: /*
36: * MSDOS doesn't have anyway of deciding whether a full-edited line
37: * is ready to be read in, so we need to do character-by-character
38: * reads, and then do the editing in the program (in the case where
39: * we are supporting line-by-line mode).
40: *
41: * The following routines, which are internal to the MSDOS-specific
42: * code, accomplish this miracle.
43: */
44:
45: #define Hex(c) HEX[(c)&0xff]
46:
47: static survivorSetup = 0; /* Do we have ^C hooks in? */
48:
49: static int
50: lineend = 0, /* There is a line terminator */
51: ctrlCCount = 0;
52:
53: static char linein[200], /* Where input line is assembled */
54: *nextin = linein, /* Next input character */
55: *nextout = linein; /* Next character to be consumed */
56:
57: static char
58: savedInState, savedOutState;
59:
60: #define consumechar() \
61: if ((++nextout) >= nextin) { \
62: nextout = nextin = linein; \
63: lineend = 0; \
64: }
65:
66: #define characteratatime() (!MODE_LINE(globalmode)) /* one by one */
67:
68:
69: /*
70: * killone()
71: *
72: * Erase the last character on the line.
73: */
74:
75: static void
76: killone()
77: {
78: if (lineend) {
79: return; /* ??? XXX */
80: }
81: if (nextin == linein) {
82: return; /* Nothing to do */
83: }
84: nextin--;
85: if (!(isspace(*nextin) || isprint(*nextin))) {
86: putchar('\b');
87: putchar(' ');
88: putchar('\b');
89: }
90: putchar('\b');
91: putchar(' ');
92: putchar('\b');
93: }
94:
95:
96: /*
97: * setlineend()
98: *
99: * Decide if it's time to send the current line up to the user
100: * process.
101: */
102:
103: static void
104: setlineend()
105: {
106: if (nextin == nextout) {
107: return;
108: }
109: if (characteratatime()) {
110: lineend = 1;
111: } else if (nextin >= (linein+sizeof linein)) {
112: lineend = 1;
113: } else {
114: int c = *(nextin-1);
115: if ((c == termIntChar)
116: || (c == termQuitChar)
117: || (c == termEofChar)) {
118: lineend = 1;
119: } else if (c == termFlushChar) {
120: lineend = 1;
121: } else if ((c == '\n') || (c == '\r')) {
122: lineend = 1;
123: }
124: }
125: /* Otherwise, leave it alone (reset by 'consumechar') */
126: }
127:
128: /*
129: * OK, what we do here is:
130: *
131: * o If we are echoing, then
132: * o Look for character erase, line kill characters
133: * o Echo the character (using '^' if a control character)
134: * o Put the character in the input buffer
135: * o Set 'lineend' as necessary
136: */
137:
138: static void
139: DoNextChar(c)
140: int c; /* Character to process */
141: {
142: static char literalnextcharacter = 0;
143:
144: if (nextin >= (linein+sizeof linein)) {
145: putchar('\7'); /* Ring bell */
146: setlineend();
147: return;
148: }
149: if (MODE_LOCAL_CHARS(globalmode)) {
150: /* Look for some special character */
151: if (!literalnextcharacter) {
152: if (c == termEraseChar) {
153: killone();
154: setlineend();
155: return;
156: } else if (c == termKillChar) {
157: while (nextin != linein) {
158: killone();
159: }
160: setlineend();
161: return;
162: } else if (c == termLiteralNextChar) {
163: literalnextcharacter = 1;
164: return;
165: }
166: }
167:
168: if (MODE_LOCAL_ECHO(globalmode)) {
169: if ((literalnextcharacter == 0) && ((c == '\r') || (c == '\n'))) {
170: putchar('\r');
171: putchar('\n');
172: c = '\n';
173: } else if (!isprint(c) && !isspace(c)) {
174: putchar('^');
175: putchar(c^0x40);
176: } else {
177: putchar(c);
178: }
179: }
180: literalnextcharacter = 0;
181: }
182: *nextin++ = c;
183: setlineend();
184: }
185:
186: static int
187: inputExists()
188: {
189: int input;
190: static state = 0;
191:
192: while (ctrlCCount) {
193: DoNextChar(0x03);
194: ctrlCCount--;
195: }
196: if (lineend) {
197: return 1;
198: }
199: #if 1 /* For BIOS variety of calls */
200: if (kbhit() == 0) {
201: return lineend;
202: }
203: input = getch(); /* MSC - get console character */
204: if ((input&0xff) == 0) {
205: DoNextChar(0x01); /* ^A */
206: } else {
207: DoNextChar(input&0xff);
208: }
209: #else /* 0 */
210: if ((input = dirconio()) == -1) {
211: return lineend;
212: }
213: if ((input&0xff) == 0) {
214: if ((input&0xff00) == 0x0300) { /* Null */
215: DoNextChar(0);
216: } else {
217: DoNextChar(0x01);
218: if (input&0x8000) {
219: DoNextChar(0x01);
220: DoNextChar((input>>8)&0x7f);
221: } else {
222: DoNextChar((input>>8)&0xff);
223: }
224: }
225: } else {
226: DoNextChar(input&0xff);
227: }
228: #endif /* 0 */
229: return lineend;
230: }
231:
232:
233: void
234: CtrlCInterrupt()
235: {
236: if (!MODE_COMMAND_LINE(globalmode)) {
237: char far *Bios_Break = (char far *) (((long)0x40<<16)|0x71);
238:
239: ctrlCCount++; /* XXX */
240: signal(SIGINT, CtrlCInterrupt);
241: } else {
242: closeallsockets();
243: exit(1);
244: }
245: }
246:
247: int
248: dosbinary(fd, onoff)
249: int fd;
250: int onoff;
251: {
252: union REGS regs;
253: int oldstate;
254:
255: /* Get old stuff */
256: regs.h.ah = 0x44;
257: regs.h.al = 0;
258: regs.x.bx = fd;
259: intdos(®s, ®s);
260: oldstate = regs.h.dl&(1<<5); /* Save state */
261:
262: /* Set correct bits in new mode */
263: regs.h.dh = 0;
264: if (onoff) {
265: regs.h.dl |= 1<<5;
266: } else {
267: regs.h.dl &= ~(1<<5);
268: }
269:
270: /* Set in new mode */
271: regs.h.ah = 0x44;
272: regs.h.al = 1;
273: regs.x.bx = fd;
274: intdos(®s, ®s);
275:
276: return oldstate;
277: }
278:
279: /*
280: * The MSDOS routines, called from elsewhere.
281: */
282:
283:
284: int
285: TerminalAutoFlush() /* MSDOS */
286: {
287: return 1;
288: }
289:
290: int
291: TerminalCanRead()
292: {
293: return inputExists();
294: }
295:
296:
297: /*
298: * Flush output to the terminal
299: */
300:
301: void
302: TerminalFlushOutput() /* MSDOS */
303: {
304: }
305:
306:
307: void
308: TerminalNewMode(fd_in, fd_out, f) /* MSDOS */
309: int fd_in, fd_out; /* File descriptors */
310: register int f;
311: {
312: union REGS inregs;
313: struct SREGS segregs;
314: static old_1b_offset = 0, old_1b_segment = 0;
315:
316: globalmode = f;
317: if (MODE_COMMAND_LINE(f)) {
318: signal(SIGINT, SIG_DFL);
319: if (old_1b_segment|old_1b_offset) {
320: inregs.h.ah = 0x25;
321: inregs.h.al = 0x1b;
322: inregs.x.dx = old_1b_offset;
323: segregs.ds = old_1b_segment;
324: intdosx(&inregs, &inregs, &segregs);
325: old_1b_segment = old_1b_offset = 0;
326: }
327: if (setmode(fd_out, O_TEXT) == -1) {
328: ExitPerror("setmode (text)", 1);
329: }
330: (void) dosbinary(fileno(stdout), 0);
331: if (setmode(fd_out, O_TEXT) == -1) {
332: ExitPerror("setmode (text)", 1);
333: }
334: (void) dosbinary(fileno(stdin), 0);
335: } else {
336: signal(SIGINT, CtrlCInterrupt);
337: if ((old_1b_segment|old_1b_offset) == 0) {
338: extern void iret_subr();
339: void (far *foo_subr)() = iret_subr;
340:
341: inregs.h.ah = 0x35;
342: inregs.h.al = 0x1b;
343: intdosx(&inregs, &inregs, &segregs);
344: old_1b_segment = segregs.es;
345: old_1b_offset = inregs.x.bx;
346: inregs.h.ah = 0x25;
347: inregs.h.al = 0x1b;
348: inregs.x.dx = FP_OFF(foo_subr);
349: segregs.ds = FP_SEG(foo_subr);
350: intdosx(&inregs, &inregs, &segregs);
351: }
352: if (MODE_LOCAL_CHARS(f)) {
353: if (setmode(fd_out, O_TEXT) == -1) {
354: ExitPerror("setmode (text)", 1);
355: }
356: (void) dosbinary(fileno(stdout), 0);
357: if (setmode(fd_in, O_TEXT) == -1) {
358: ExitPerror("setmode (text)", 1);
359: }
360: (void) dosbinary(fileno(stdin), 0);
361: } else {
362: if (setmode(fd_out, O_BINARY) == -1) {
363: ExitPerror("setmode (binary)", 1);
364: }
365: (void) dosbinary(fileno(stdout), 1);
366: if (setmode(fd_in, O_BINARY) == -1) {
367: ExitPerror("setmode (binary)", 1);
368: }
369: (void) dosbinary(fileno(stdin), 1);
370: }
371: }
372: }
373:
374: int
375: TerminalRead(fd, buffer, count)
376: int fd;
377: char *buffer;
378: int count;
379: {
380: int done = 0;
381:
382: for (;;) {
383: while (inputExists() && (done < count)) {
384: *buffer++ = *nextout;
385: consumechar();
386: done++;
387: }
388: if (done) {
389: return(done);
390: } else {
391: return 0;
392: }
393: }
394: }
395:
396:
397: void
398: TerminalSaveState() /* MSDOS */
399: {
400: termEofChar = '\4';
401: termEraseChar = '\10';
402: termFlushChar = '\17';
403: termIntChar = '\3';
404: termKillChar = '\25';
405: termLiteralNextChar = '\26';
406: termQuitChar = '\0';;
407:
408: savedInState = dosbinary(fileno(stdin), 0);
409: savedOutState = dosbinary(fileno(stdout), 0);
410: }
411:
412: int
413: TerminalSpecialChars(c) /* MSDOS */
414: {
415: return 1;
416: }
417:
418:
419: void
420: TerminalRestoreState() /* MSDOS */
421: {
422: (void) dosbinary(fileno(stdin), savedInState);
423: (void) dosbinary(fileno(stdout), savedOutState);
424: }
425:
426:
427: int
428: TerminalWrite(fd, buffer, count) /* MSDOS */
429: int fd;
430: char *buffer;
431: int count;
432: {
433: return fwrite(buffer, sizeof (char), count, stdout); /* XXX */
434: }
435:
436:
437: int
438: NetClose(fd)
439: {
440: return closesocket(fd);
441: }
442:
443: void
444: NetNonblockingIO(fd, onoff) /* MSDOS */
445: int
446: fd,
447: onoff;
448: {
449: if (SetSockOpt(fd, SOL_SOCKET, SO_NONBLOCKING, onoff)) {
450: perror("setsockop (SO_NONBLOCKING) ");
451: ExitString(stderr, "exiting\n", 1);
452: }
453: }
454:
455: void
456: NetSigIO(fd) /* MSDOS */
457: int fd;
458: {
459: }
460:
461: void
462: NetSetPgrp(fd) /* MSDOS */
463: int fd;
464: {
465: }
466:
467:
468: #endif /* defined(MSDOS) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.