]> git.pond.sub.org Git - empserver/blob - src/client/termio.c
6a597efdfb360f124b91bcad78ef3b2472f1e3ad
[empserver] / src / client / termio.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  termio.c: Various io functions
29  * 
30  *  Known contributors to this file:
31  *     Steve McClure, 1998
32  */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <sys/types.h>
37 #if defined(aix) || defined(hpux) || defined(sgi)
38 #include <sys/termio.h>
39 #elif defined(linux)
40 #include <unistd.h>
41 #include <termio.h>
42 #else
43 #ifndef _WIN32
44 #include <unistd.h>
45 #include <sgtty.h>
46 #else
47 #include <winsock.h>
48 #endif /* _WIN32 */
49 #endif
50 #include "misc.h"
51 #include "tags.h"
52
53 extern struct tagstruct *taglist;
54 extern s_char buf[4096];
55 extern s_char exec[];
56
57 #ifdef _WIN32
58 extern HANDLE hStdIn;
59 #endif
60
61 int sendeof();
62
63 int
64 termio(fd, sock, auxfi)
65 int fd;
66 int sock;
67 FILE *auxfi;
68 {
69     s_char out[4096];
70     int i, n;
71     s_char *ptr;
72     s_char *p, *q, *r, *s, *t;
73     int nbytes;
74     int numarg, prespace, exec_com, inarg, quoted, tagging;
75     struct tagstruct *tag;
76 #ifdef _WIN32
77     char c;
78     INPUT_RECORD InpBuffer[2];
79     int err;
80 #endif
81
82     i = strlen(buf);
83     p = buf + i;
84 #ifndef _WIN32
85     n = read(fd, p, sizeof(buf) - i);
86 #else
87 /* The keyboard is sometimes generating both keydown and keyup
88  * events for the same key.  Thus, we only want to grab keydown
89  * events. */
90     if (fd == -1) {
91         err = PeekConsoleInput(hStdIn, InpBuffer, 1, &n);
92         if (InpBuffer[0].EventType != KEY_EVENT) {
93             ReadConsoleInput(hStdIn, InpBuffer, 1, &n);
94             return 1;
95         }
96         if (!InpBuffer[0].Event.KeyEvent.bKeyDown) {
97             ReadConsoleInput(hStdIn, InpBuffer, 1, &n);
98             return 1;
99         }
100         c = InpBuffer[0].Event.KeyEvent.uChar.AsciiChar;
101
102         if (c == 13)
103             c = 10;
104         n = 1;
105         p[0] = c;
106         p[1] = '\0';
107         if (c != 10)
108             ReadConsole(hStdIn, &p[0], sizeof(buf) - i, &n, NULL);
109         else
110             putchar(c);
111 /* Strip off the CRLF to just LF */
112         if (n > 1) {
113             if (p[n - 2] == 13 && p[n - 1] == 10) {
114                 p[n - 2] = 10;
115                 p[n - 1] = 0;
116                 n--;
117             }
118         }
119         FlushConsoleInputBuffer(hStdIn);
120     } else {
121         n = read(fd, p, sizeof(buf) - i);
122     }
123 #endif
124     if (n == 0) {
125         sendeof(sock);
126         return 0;
127     }
128     if (n < 0) {
129         perror("read standard input");
130         return 0;
131     }
132     n += i;
133     ptr = buf;
134     p = buf;
135     q = out;
136     r = out;
137     numarg = 0;
138     tagging = 0;
139     inarg = 0;
140     prespace = 1;
141     quoted = 0;
142     while (p < buf + n && q < out + 4000) {
143         if (*p == '\n') {
144             if (tagging) {
145                 tag = (struct tagstruct *)malloc(sizeof(struct tagstruct));
146                 tag->item = (s_char *)malloc((1 + p - s) * sizeof(s_char));
147                 tag->next = taglist;
148                 taglist = tag;
149                 t = tag->item;
150                 while (s < p)
151                     *t++ = *s++;
152                 *t = 0;
153             }
154             *q++ = *p++;
155             numarg = 0;
156             tagging = 0;
157             inarg = 0;
158             prespace = 1;
159             quoted = 0;
160             ptr = p;
161             r = q;
162         } else if (tagging) {
163             *q++ = *p++;
164         } else if (!quoted && isspace(*p)) {
165             *q++ = *p++;
166             prespace = 1;
167             if (numarg == 1 && exec_com && s > exec + 2) {
168                 tagging = 1;
169                 s = p;
170             }
171         } else if (prespace && *p == '|') {
172             tagging = 1;
173             *q++ = *p++;
174             s = p;
175         } else if (prespace && *p == '>') {
176             tagging = 1;
177             *q++ = *p++;
178             if (*p != '\n' && (*p == '!' || *p == '>'))
179                 *q++ = *p++;
180             s = p;
181         } else {
182             prespace = 0;
183             if (*p == '"') {
184                 quoted = !quoted;
185             } else {
186                 if (!inarg && *p != '?') {
187                     s = exec;
188                     exec_com = 1;
189                     numarg++;
190                 }
191                 inarg = 1;
192                 if (*s && *s++ != *p)
193                     exec_com = 0;
194             }
195             *q++ = *p++;
196         }
197     }
198     p = buf;
199     while (ptr < buf + n)
200         *p++ = *ptr++;
201     *p = 0;
202     ptr = out;
203     n = r - out;
204     if (auxfi) {
205         fwrite(out, n, 1, auxfi);
206     }
207     while (n > 0) {
208 #ifndef _WIN32
209         nbytes = write(sock, ptr, n);
210 #else
211         nbytes = send(sock, ptr, n, 0);
212 #endif
213         if (nbytes <= 0) {
214 #ifdef _WIN32
215             errno = WSAGetLastError();
216 #endif
217             perror("write server socket");
218             return 0;
219         }
220         ptr += nbytes;
221         n -= nbytes;
222     }
223     return 1;
224 }
225
226 int
227 sendeof(sock)
228 int sock;
229 {
230 #ifndef _WIN32
231     if (write(sock, "ctld\n", 5) < 5) {
232 #else
233     if (send(sock, "ctld\n", 5, 0) < 5) {
234 #endif
235         fprintf(stderr, "sendeof: EOF send failed\n");
236         close(sock);
237         return 0;
238     }
239     return 1;
240 }
241
242 int echomode = 1;
243
244 #if defined(hpux) || defined(aix) || defined (sgi) || defined(linux)
245 void
246 _noecho(fd)
247 int fd;
248 {
249     struct termio io;
250
251     echomode = 0;
252     (void)ioctl(fd, TCGETA, &io);
253     io.c_line |= ECHO;
254     (void)ioctl(fd, TCSETA, &io);
255 }
256
257 void
258 _echo(fd)
259 int fd;
260 {
261     struct termio io;
262
263     if (echomode)
264         return;
265     (void)ioctl(fd, TCGETA, &io);
266     io.c_line &= ~ECHO;
267     (void)ioctl(fd, TCSETA, &io);
268     echomode++;
269 }
270
271 #else
272 #ifndef _WIN32
273
274 void
275 _noecho(fd)
276 int fd;
277 {
278     struct sgttyb sgbuf;
279
280     echomode = 0;
281     (void)ioctl(fd, TIOCGETP, &sgbuf);
282     sgbuf.sg_flags &= ~ECHO;
283     (void)ioctl(fd, TIOCSETP, &sgbuf);
284 }
285
286 void
287 _echo(fd)
288 int fd;
289 {
290     struct sgttyb sgbuf;
291
292     if (echomode)
293         return;
294     (void)ioctl(fd, TIOCGETP, &sgbuf);
295     sgbuf.sg_flags |= ECHO;
296     (void)ioctl(0, TIOCSETP, &sgbuf);
297     echomode++;
298 }
299 #else
300 void
301 _noecho(fd)
302 int fd;
303 {
304     echomode = 0;
305 }
306
307 void
308 _echo(fd)
309 int fd;
310 {
311     echomode++;
312 }
313
314 #endif /* _WIN32 */
315 #endif