]> git.pond.sub.org Git - empserver/blob - src/client/termio.c
Indented with src/scripts/indent-emp.
[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 <sys/types.h>
36 #if defined(aix) || defined(hpux) || defined(sgi)
37 #include <sys/termio.h>
38 #elif defined(linux)
39 #include <unistd.h>
40 #include <termio.h>
41 #else
42 #ifndef _WIN32
43 #include <unistd.h>
44 #include <sgtty.h>
45 #else
46 #include <winsock.h>
47 #endif /* _WIN32 */
48 #endif
49 #include "misc.h"
50 #include "tags.h"
51
52 extern struct tagstruct *taglist;
53 extern s_char buf[4096];
54 extern s_char exec[];
55
56 #ifdef _WIN32
57 extern HANDLE hStdIn;
58 #endif
59
60 int sendeof();
61
62 int
63 termio(fd, sock, auxfi)
64 int fd;
65 int sock;
66 FILE *auxfi;
67 {
68     s_char out[4096];
69     int i, n;
70     s_char *ptr;
71     s_char *p, *q, *r, *s, *t;
72     int nbytes;
73     int numarg, prespace, exec_com, inarg, quoted, tagging;
74     struct tagstruct *tag;
75 #ifdef _WIN32
76     char c;
77     INPUT_RECORD InpBuffer[2];
78     int err;
79 #endif
80
81     i = strlen(buf);
82     p = buf + i;
83 #ifndef _WIN32
84     n = read(fd, p, sizeof(buf) - i);
85 #else
86 /* The keyboard is sometimes generating both keydown and keyup
87  * events for the same key.  Thus, we only want to grab keydown
88  * events. */
89     if (fd == -1) {
90         err = PeekConsoleInput(hStdIn, InpBuffer, 1, &n);
91         if (InpBuffer[0].EventType != KEY_EVENT) {
92             ReadConsoleInput(hStdIn, InpBuffer, 1, &n);
93             return 1;
94         }
95         if (!InpBuffer[0].Event.KeyEvent.bKeyDown) {
96             ReadConsoleInput(hStdIn, InpBuffer, 1, &n);
97             return 1;
98         }
99         c = InpBuffer[0].Event.KeyEvent.uChar.AsciiChar;
100
101         if (c == 13)
102             c = 10;
103         n = 1;
104         p[0] = c;
105         p[1] = '\0';
106         if (c != 10)
107             ReadConsole(hStdIn, &p[0], sizeof(buf) - i, &n, NULL);
108         else
109             putchar(c);
110 /* Strip off the CRLF to just LF */
111         if (n > 1) {
112             if (p[n - 2] == 13 && p[n - 1] == 10) {
113                 p[n - 2] = 10;
114                 p[n - 1] = 0;
115                 n--;
116             }
117         }
118         FlushConsoleInputBuffer(hStdIn);
119     } else {
120         n = read(fd, p, sizeof(buf) - i);
121     }
122 #endif
123     if (n == 0) {
124         sendeof(sock);
125         return 0;
126     }
127     if (n < 0) {
128         perror("read standard input");
129         return 0;
130     }
131     n += i;
132     ptr = buf;
133     p = buf;
134     q = out;
135     r = out;
136     numarg = 0;
137     tagging = 0;
138     inarg = 0;
139     prespace = 1;
140     quoted = 0;
141     while (p < buf + n && q < out + 4000) {
142         if (*p == '\n') {
143             if (tagging) {
144                 tag = (struct tagstruct *)malloc(sizeof(struct tagstruct));
145                 tag->item = (s_char *)malloc((1 + p - s) * sizeof(s_char));
146                 tag->next = taglist;
147                 taglist = tag;
148                 t = tag->item;
149                 while (s < p)
150                     *t++ = *s++;
151                 *t = 0;
152             }
153             *q++ = *p++;
154             numarg = 0;
155             tagging = 0;
156             inarg = 0;
157             prespace = 1;
158             quoted = 0;
159             ptr = p;
160             r = q;
161         } else if (tagging) {
162             *q++ = *p++;
163         } else if (!quoted && isspace(*p)) {
164             *q++ = *p++;
165             prespace = 1;
166             if (numarg == 1 && exec_com && s > exec + 2) {
167                 tagging = 1;
168                 s = p;
169             }
170         } else if (prespace && *p == '|') {
171             tagging = 1;
172             *q++ = *p++;
173             s = p;
174         } else if (prespace && *p == '>') {
175             tagging = 1;
176             *q++ = *p++;
177             if (*p != '\n' && (*p == '!' || *p == '>'))
178                 *q++ = *p++;
179             s = p;
180         } else {
181             prespace = 0;
182             if (*p == '"') {
183                 quoted = !quoted;
184             } else {
185                 if (!inarg && *p != '?') {
186                     s = exec;
187                     exec_com = 1;
188                     numarg++;
189                 }
190                 inarg = 1;
191                 if (*s && *s++ != *p)
192                     exec_com = 0;
193             }
194             *q++ = *p++;
195         }
196     }
197     p = buf;
198     while (ptr < buf + n)
199         *p++ = *ptr++;
200     *p = 0;
201     ptr = out;
202     n = r - out;
203     if (auxfi) {
204         fwrite(out, n, 1, auxfi);
205     }
206     while (n > 0) {
207 #ifndef _WIN32
208         nbytes = write(sock, ptr, n);
209 #else
210         nbytes = send(sock, ptr, n, 0);
211 #endif
212         if (nbytes <= 0) {
213 #ifdef _WIN32
214             errno = WSAGetLastError();
215 #endif
216             perror("write server socket");
217             return 0;
218         }
219         ptr += nbytes;
220         n -= nbytes;
221     }
222     return 1;
223 }
224
225 int
226 sendeof(sock)
227 int sock;
228 {
229 #ifndef _WIN32
230     if (write(sock, "ctld\n", 5) < 5) {
231 #else
232     if (send(sock, "ctld\n", 5, 0) < 5) {
233 #endif
234         fprintf(stderr, "sendeof: EOF send failed\n");
235         close(sock);
236         return 0;
237     }
238     return 1;
239 }
240
241 int echomode = 1;
242
243 #if defined(hpux) || defined(aix) || defined (sgi) || defined(linux)
244 void
245 _noecho(fd)
246 int fd;
247 {
248     struct termio io;
249
250     echomode = 0;
251     (void)ioctl(fd, TCGETA, &io);
252     io.c_line |= ECHO;
253     (void)ioctl(fd, TCSETA, &io);
254 }
255
256 void
257 _echo(fd)
258 int fd;
259 {
260     struct termio io;
261
262     if (echomode)
263         return;
264     (void)ioctl(fd, TCGETA, &io);
265     io.c_line &= ~ECHO;
266     (void)ioctl(fd, TCSETA, &io);
267     echomode++;
268 }
269
270 #else
271 #ifndef _WIN32
272
273 void
274 _noecho(fd)
275 int fd;
276 {
277     struct sgttyb sgbuf;
278
279     echomode = 0;
280     (void)ioctl(fd, TIOCGETP, &sgbuf);
281     sgbuf.sg_flags &= ~ECHO;
282     (void)ioctl(fd, TIOCSETP, &sgbuf);
283 }
284
285 void
286 _echo(fd)
287 int fd;
288 {
289     struct sgttyb sgbuf;
290
291     if (echomode)
292         return;
293     (void)ioctl(fd, TIOCGETP, &sgbuf);
294     sgbuf.sg_flags |= ECHO;
295     (void)ioctl(0, TIOCSETP, &sgbuf);
296     echomode++;
297 }
298 #else
299 void
300 _noecho(fd)
301 int fd;
302 {
303     echomode = 0;
304 }
305
306 void
307 _echo(fd)
308 int fd;
309 {
310     echomode++;
311 }
312
313 #endif /* _WIN32 */
314 #endif