BSD 4_3_Net_1 release
[unix-history] / telnet / Source / sys_dos.c
CommitLineData
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 19static 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
52static survivorSetup = 0; /* Do we have ^C hooks in? */
53
54static int
55 lineend = 0, /* There is a line terminator */
56 ctrlCCount = 0;
57
58static char linein[200], /* Where input line is assembled */
59 *nextin = linein, /* Next input character */
60 *nextout = linein; /* Next character to be consumed */
61
62static 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
80static void
81killone()
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
108static void
109setlineend()
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
143static void
144DoNextChar(c)
145int 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
191static int
192inputExists()
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
238void
239CtrlCInterrupt()
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
252int
253dosbinary(fd, onoff)
254int fd;
255int 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(&regs, &regs);
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(&regs, &regs);
280
281 return oldstate;
282}
283\f
284/*
285 * The MSDOS routines, called from elsewhere.
286 */
287
288
289int
290TerminalAutoFlush() /* MSDOS */
291{
292 return 1;
293}
294
295int
296TerminalCanRead()
297{
298 return inputExists();
299}
300
301
302/*
303 * Flush output to the terminal
304 */
305
306void
307TerminalFlushOutput() /* MSDOS */
308{
309}
310
311
312void
313TerminalNewMode(fd_in, fd_out, f) /* MSDOS */
314int fd_in, fd_out; /* File descriptors */
315register 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
379int
380TerminalRead(fd, buffer, count)
381int fd;
382char *buffer;
383int 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
402void
403TerminalSaveState() /* 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
417int
418TerminalSpecialChars(c) /* MSDOS */
419{
420 return 1;
421}
422
423
424void
425TerminalRestoreState() /* MSDOS */
426{
427 (void) dosbinary(fileno(stdin), savedInState);
428 (void) dosbinary(fileno(stdout), savedOutState);
429}
430
431
432int
433TerminalWrite(fd, buffer, count) /* MSDOS */
434int fd;
435char *buffer;
436int count;
437{
438 return fwrite(buffer, sizeof (char), count, stdout); /* XXX */
439}
440
441
442int
443NetClose(fd)
444{
445 return closesocket(fd);
446}
447
448void
449NetNonblockingIO(fd, onoff) /* MSDOS */
450int
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
460void
461NetSigIO(fd) /* MSDOS */
462int fd;
463{
464}
465
466void
467NetSetPgrp(fd) /* MSDOS */
468int fd;
469{
470}
471
472
473#endif /* defined(MSDOS) */