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