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