]> git.pond.sub.org Git - empserver/blob - src/client/termio.c
Import of Empire 4.2.12
[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) *t++ = *s++;
150                                 *t = 0;
151                         }
152                         *q++ = *p++;
153                         numarg = 0;
154                         tagging = 0;
155                         inarg = 0;
156                         prespace = 1;
157                         quoted = 0;
158                         ptr = p;
159                         r = q;
160                 } else if (tagging) {
161                         *q++ = *p++;
162                 } else if (!quoted && isspace(*p)) {
163                         *q++ = *p++;
164                         prespace = 1;
165                         if (numarg == 1 && exec_com && s > exec + 2) {
166                                 tagging = 1;
167                                 s = p;
168                         }
169                 } else if (prespace && *p == '|') {
170                         tagging = 1;
171                         *q++ = *p++;
172                         s = p;
173                 } else if (prespace && *p == '>') {
174                         tagging = 1;
175                         *q++ = *p++;
176                         if (*p != '\n' && (*p == '!' || *p == '>')) *q++ = *p++;
177                         s = p;
178                 } else {
179                         prespace = 0;
180                         if (*p == '"') {
181                                 quoted = !quoted;
182                         } else {
183                                 if (!inarg && *p != '?') {
184                                         s = exec;
185                                         exec_com = 1;
186                                         numarg++;
187                                 }
188                                 inarg = 1;
189                                 if (*s && *s++ != *p) exec_com = 0;
190                         }
191                         *q++ = *p++;
192                 }
193         }
194         p = buf;
195         while (ptr < buf + n) *p++ = *ptr++;
196         *p = 0;
197         ptr = out;
198         n = r - out;
199         if (auxfi) {
200             fwrite(out, n, 1, auxfi);
201         }
202         while (n > 0) {
203 #ifndef _WIN32
204                 nbytes = write(sock, ptr, n);
205 #else
206                 nbytes = send(sock, ptr, n, 0);
207 #endif
208                 if (nbytes <= 0) {
209 #ifdef _WIN32
210                         errno = WSAGetLastError();
211 #endif
212                         perror("write server socket");
213                         return 0;
214                 }
215                 ptr += nbytes;
216                 n -= nbytes;
217         }
218         return 1;
219 }
220
221 int
222 sendeof(sock)
223         int     sock;
224 {
225 #ifndef _WIN32
226         if (write(sock, "ctld\n", 5) < 5) {
227 #else
228         if (send(sock, "ctld\n", 5, 0) < 5) {
229 #endif
230                 fprintf(stderr, "sendeof: EOF send failed\n");
231                 close(sock);
232                 return 0;
233         }
234         return 1;
235 }
236
237 int     echomode = 1;
238
239 #if defined(hpux) || defined(aix) || defined (sgi) || defined(linux)
240 void
241 _noecho(fd)
242         int     fd;
243 {
244         struct  termio io;
245
246         echomode = 0;
247         (void) ioctl(fd, TCGETA, &io);
248         io.c_line |= ECHO;
249         (void) ioctl(fd, TCSETA, &io);
250 }
251
252 void
253 _echo(fd)
254         int     fd;
255 {
256         struct  termio io;
257
258         if (echomode)
259                 return;
260         (void) ioctl(fd, TCGETA, &io);
261         io.c_line &= ~ECHO;
262         (void) ioctl(fd, TCSETA, &io);
263         echomode++;
264 }
265
266 #else
267 #ifndef _WIN32
268
269 void
270 _noecho(fd)
271         int     fd;
272 {
273         struct  sgttyb sgbuf;
274
275         echomode = 0;
276         (void) ioctl(fd, TIOCGETP, &sgbuf);
277         sgbuf.sg_flags &= ~ECHO;
278         (void) ioctl(fd, TIOCSETP, &sgbuf);
279 }
280
281 void
282 _echo(fd)
283         int     fd;
284 {
285         struct  sgttyb sgbuf;
286
287         if (echomode)
288                 return;
289         (void) ioctl(fd, TIOCGETP, &sgbuf);
290         sgbuf.sg_flags |= ECHO;
291         (void) ioctl(0, TIOCSETP, &sgbuf);
292         echomode++;
293 }
294 #else
295 void
296 _noecho(fd)
297 int fd;
298 {
299         echomode = 0;
300 }
301
302 void
303 _echo(fd)
304 int fd;
305 {
306         echomode++;
307 }
308
309 #endif /* _WIN32 */
310 #endif