]> git.pond.sub.org Git - empserver/blob - src/client/termio.c
(main): Don't bother to close socket before exit().
[empserver] / src / client / termio.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2007, 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 files README, COPYING and CREDITS in the root of the source
23  *  tree for related information and legal notices.  It is expected
24  *  that future 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 <config.h>
35
36 #include <ctype.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #ifdef _WIN32
41 #include <io.h>
42 #else
43 #include <unistd.h>
44 #endif
45 #include "misc.h"
46 #include "tags.h"
47
48 static int sendeof(int sock);
49
50 int
51 termio(int fd, int sock, FILE *auxfi)
52 {
53     static char exec[] = "execute";
54     static char buf[4096];
55     char out[4096];
56     int i, n;
57     char *ptr;
58     char *p, *q, *r, *s, *t;
59     int nbytes;
60     int prespace, exec_com, inarg, quoted, tagging;
61     struct tagstruct *tag;
62 #ifdef _WIN32
63     char c;
64     INPUT_RECORD InpBuffer[2];
65     int ret;
66     DWORD records;
67 #endif
68
69     i = strlen(buf);
70     p = buf + i;
71 #ifndef _WIN32
72     n = read(fd, p, sizeof(buf) - i);
73 #else
74 /* The keyboard is sometimes generating both keydown and keyup
75  * events for the same key.  Thus, we only want to grab keydown
76  * events. */
77     if (fd == -1) {
78         ret = PeekConsoleInput(hStdIn, InpBuffer, 1, &records);
79         if (!ret) {
80             fprintf(stderr, "Error peeking the console input (%lu)\n",
81                 GetLastError());
82             return 0;
83         }
84         if (records == 0)
85             return 0;
86         if (InpBuffer[0].EventType != KEY_EVENT) {
87             ret = ReadConsoleInput(hStdIn, InpBuffer, 1, &records);
88             if (!ret) {
89                 fprintf(stderr, "Error reading the console input (%lu)\n",
90                     GetLastError());
91                 return 0;
92             }
93             if (records == 0)
94                 return 0;
95             return 1;
96         }
97         if (!InpBuffer[0].Event.KeyEvent.bKeyDown) {
98             ret = ReadConsoleInput(hStdIn, InpBuffer, 1, &records);
99             if (!ret) {
100                 fprintf(stderr, "Error reading the console input (%lu)\n",
101                     GetLastError());
102                 return 0;
103             }
104             if (records == 0)
105                 return 0;
106             return 1;
107         }
108         c = InpBuffer[0].Event.KeyEvent.uChar.AsciiChar;
109
110         if (c == 13)
111             c = 10;
112         records = 1;
113         p[0] = c;
114         p[1] = '\0';
115         if (c != 10) {
116             ret = ReadConsole(hStdIn, p, sizeof(buf) - i, &records, NULL);
117             if (!ret) {
118                 fprintf(stderr, "Error reading the console (%lu)\n",
119                     GetLastError());
120                 return 0;
121             }
122         } else
123             putchar(c);
124 /* Strip off the CRLF to just LF */
125         if (records > 1) {
126             if (p[records - 2] == 13 && p[records - 1] == 10) {
127                 p[records - 2] = 10;
128                 p[records - 1] = 0;
129                 records--;
130             }
131         }
132         FlushConsoleInputBuffer(hStdIn);
133         if (records == 0)
134             return 0;
135         n = records;
136     } else if (fd == 0) {
137         if (feof(stdin)) {
138             sendeof(sock);
139             return 0;
140         }
141         fgets(p, sizeof(buf) - i, stdin);
142         n = strlen(p);
143     } else {
144         n = read(fd, p, sizeof(buf) - i);
145     }
146 #endif
147     if (n == 0) {
148         sendeof(sock);
149         return 0;
150     }
151     if (n < 0) {
152         perror("read standard input");
153         return 0;
154     }
155     n += i;
156     ptr = buf;
157     p = buf;
158     q = out;
159     r = out;
160     tagging = 0;
161     inarg = 0;
162     prespace = 1;
163     quoted = 0;
164     exec_com = 0;
165     while (p < buf + n && q < out + 4000) {
166         if (*p == '\n') {
167             if (tagging) {
168                 tag = malloc(sizeof(struct tagstruct));
169                 tag->item = malloc(1 + p - s);
170                 tag->next = taglist;
171                 taglist = tag;
172                 t = tag->item;
173                 while (s < p)
174                     *t++ = *s++;
175                 *t = 0;
176             }
177             *q++ = *p++;
178             tagging = 0;
179             inarg = 0;
180             prespace = 1;
181             quoted = 0;
182             exec_com = 0;
183             ptr = p;
184             r = q;
185         } else if (tagging) {
186             *q++ = *p++;
187         } else if (!quoted && isspace(*p)) {
188             *q++ = *p++;
189             prespace = 1;
190             if (exec_com && s > exec + 2) {
191                 tagging = 1;
192                 s = p;
193             }
194         } else if (prespace && *p == '|') {
195             tagging = 1;
196             *q++ = *p++;
197             s = p;
198         } else if (prespace && *p == '>') {
199             tagging = 1;
200             *q++ = *p++;
201             if (*p != '\n' && (*p == '!' || *p == '>'))
202                 *q++ = *p++;
203             s = p;
204         } else {
205             prespace = 0;
206             if (*p == '"') {
207                 quoted = !quoted;
208             } else {
209                 if (!inarg && *p != '?') {
210                     s = exec;
211                     exec_com = 1;
212                     inarg = 1;
213                 }
214                 if (exec_com && *s && *s++ != *p)
215                     exec_com = 0;
216             }
217             *q++ = *p++;
218         }
219     }
220     p = buf;
221     while (ptr < buf + n)
222         *p++ = *ptr++;
223     *p = 0;
224     ptr = out;
225     n = r - out;
226     if (auxfi) {
227         fwrite(out, n, 1, auxfi);
228     }
229     while (n > 0) {
230 #ifndef _WIN32
231         nbytes = write(sock, ptr, n);
232 #else
233         nbytes = send(sock, ptr, n, 0);
234 #endif
235         if (nbytes <= 0) {
236 #ifdef _WIN32
237             errno = WSAGetLastError();
238 #endif
239             perror("write server socket");
240             return 0;
241         }
242         ptr += nbytes;
243         n -= nbytes;
244     }
245     return 1;
246 }
247
248 static int
249 sendeof(int sock)
250 {
251 #ifndef _WIN32
252     if (write(sock, "ctld\n", 5) < 5) {
253 #else
254     if (send(sock, "ctld\n", 5, 0) < 5) {
255 #endif
256         fprintf(stderr, "sendeof: EOF send failed\n");
257 #ifdef _WIN32
258         closesocket(sock);
259 #else
260         close(sock);
261 #endif
262         return 0;
263     }
264     return 1;
265 }