]> git.pond.sub.org Git - empserver/blob - src/client/servcmd.c
(io_gets, output): Remove the removal of \n in io_gets() and the
[empserver] / src / client / servcmd.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2005, 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  *  servercmd.c: Change the state depending on the command from the server.
29  * 
30  *  Known contributors to this file:
31  *     Dave Pare, 1989
32  *     Steve McClure, 1998
33  */
34
35 #include "misc.h"
36 #include "proto.h"
37 #include "queue.h"
38 #include "ioqueue.h"
39 #include "tags.h"
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <ctype.h>
45 #include <fcntl.h>
46 #if !defined(_WIN32)
47 #include <unistd.h>
48 #else
49 #include <io.h>
50 #endif
51
52 char num_teles[64];
53 static char the_prompt[1024];
54 static int mode;
55 static int nbtu;
56 static int nmin;
57 FILE *redir_fp;
58 FILE *pipe_fp;
59 int exec_fd;
60
61 static void prompt(FILE *auxfi);
62 static void doredir(char *p);
63 static void dopipe(char *p);
64 static void doexecute(char *p, FILE *auxfi);
65 static void output(int code, char *buf, FILE *auxfi, int eol);
66 static void screen(char *buf);
67
68 void
69 servercmd(struct ioqueue *ioq, FILE *auxfi)
70 {
71     char buf[1024];
72     char *p;
73     static int code = -1;
74     int eol;
75
76     while (ioq_gets(ioq, buf, sizeof(buf), &eol)) {
77         p = buf;
78         if (code == -1) {
79             if (isalpha(*buf))
80                 code = 10 + (*buf - 'a');
81             else
82                 code = *buf - '0';
83             while (*p && !isspace(*p))
84                 p++;
85             *p++ = 0;
86         }
87         switch (code) {
88         case C_PROMPT:
89             if (sscanf(p, "%d %d", &nmin, &nbtu) != 2) {
90                 fprintf(stderr, "prompt: bad server prompt %s\n", p);
91             }
92             mode = code;
93             sprintf(the_prompt, "[%d:%d] Command : ", nmin, nbtu);
94             prompt(auxfi);
95             break;
96         case C_REDIR:
97             doredir(p);
98             break;
99         case C_PIPE:
100             dopipe(p);
101             break;
102         case C_FLUSH:
103             mode = code;
104             sprintf(the_prompt, "%s", p);
105             prompt(auxfi);
106             break;
107         case C_EXECUTE:
108             doexecute(p, auxfi);
109             break;
110         case C_INFORM:
111             if (*p) {
112                 p[strlen(p) - 1] = '\0';
113                 sprintf(num_teles, "(%s) ", p + 1);
114                 if (!redir_fp && !pipe_fp && !exec_fd) {
115                     putchar('\07');
116                     prompt(NULL);
117                 }
118             } else
119                 *num_teles = '\0';
120             break;
121         default:
122             output(code, p, auxfi, eol);
123             break;
124         }
125         if (eol)
126             code = -1;
127     }
128 }
129
130 static void
131 prompt(FILE *auxfi)
132 {
133     if (mode == C_PROMPT) {
134         if (redir_fp) {
135             (void)fclose(redir_fp);
136             redir_fp = NULL;
137         } else if (pipe_fp) {
138             (void)pclose(pipe_fp);
139             pipe_fp = NULL;
140         } else if (exec_fd > 0) {
141             close(exec_fd);
142             close(0);
143             exec_fd = -1;
144             open("/dev/tty", O_RDONLY, 0);
145         }
146     }
147     if (mode == C_PROMPT)
148         printf("\n");
149     printf("%s%s", num_teles, the_prompt);
150     (void)fflush(stdout);
151     if (auxfi) {
152         fprintf(auxfi, "\n%s%s", num_teles, the_prompt);
153         (void)fflush(auxfi);
154     }
155 }
156
157 /*
158  * opens redir_fp if successful
159  */
160 static void
161 doredir(char *p)
162 {
163     char *how;
164     char *name;
165     char *tag;
166     int mode;
167     int fd;
168
169     if (redir_fp) {
170         (void)fclose(redir_fp);
171         redir_fp = NULL;
172     }
173     how = p++;
174     if (*p && ((*p == '>') || (*p == '!')))
175         p++;
176     tag = gettag(p);
177     while (*p && isspace(*p))
178         p++;
179     name = p;
180     while (*p && !isspace(*p))
181         p++;
182     *p = 0;
183     if (tag == NULL) {
184         fprintf(stderr, "WARNING!  Server redirected output to file %s\n",
185                 name);
186         return;
187     }
188     mode = O_WRONLY | O_CREAT;
189     if (how[1] == '>')
190         mode |= O_APPEND;
191     else if (how[1] == '!')
192         mode |= O_TRUNC;
193     else
194         mode |= O_EXCL;
195     if (*name == 0) {
196         fprintf(stderr, "Null file name after redirect\n");
197         free(tag);
198         return;
199     }
200     if ((fd = open(name, mode, 0600)) < 0) {
201         fprintf(stderr, "Redirect open failed\n");
202         perror(name);
203     } else {
204         redir_fp = fdopen(fd, "w");
205     }
206     free(tag);
207 }
208
209 /*
210  * opens "pipe_fp" if successful
211  */
212 static void
213 dopipe(char *p)
214 {
215     char *tag;
216
217     if (*p == '|')
218         p++;
219     tag = gettag(p);
220     while (*p && isspace(*p))
221         p++;
222     if (tag == NULL) {
223         fprintf(stderr, "WARNING!  Server attempted to run: %s\n", p);
224         return;
225     }
226     if (*p == 0) {
227         fprintf(stderr, "Null program name after redirect\n");
228         free(tag);
229         return;
230     }
231     if ((pipe_fp = popen(p, "w")) == NULL) {
232         fprintf(stderr, "Pipe open failed\n");
233         perror(p);
234     }
235     free(tag);
236 }
237
238 static void
239 doexecute(char *p, FILE *auxfi)
240 {
241     int fd;
242     char *tag;
243
244     tag = gettag(p);
245     while (*p && isspace(*p))
246         p++;
247     if (tag == NULL) {
248         fprintf(stderr,
249                 "WARNING!  Server attempted unauthorized read of file %s\n",
250                 p);
251         return;
252     }
253     if (p == NULL) {
254         fprintf(stderr, "Null file to execute\n");
255         free(tag);
256         return;
257     }
258     if ((fd = open(p, O_RDONLY, 0)) < 0) {
259         fprintf(stderr, "Can't open execute file\n");
260         perror(p);
261         free(tag);
262         return;
263     }
264     /* copies 4k at a time to the socket */
265     while (termio(fd, sock, auxfi))     /*do copy */
266         ;
267     /* Some platforms don't send the eof (cntl-D) at the end of
268        copying a file.  If emp_client hangs at the end of an
269        execute, include the following line and notify wolfpack
270        of the platform you are using.
271        sendeof(sock);
272      */
273     close(fd);
274     free(tag);
275 }
276
277 static void
278 output(int code, char *buf, FILE *auxfi, int eol)
279 {
280     switch (code) {
281     case C_NOECHO:
282         /* not implemented; serve doesn't send it */
283         break;
284     case C_FLUSH:
285         (void)fflush(stdout);
286         if (auxfi)
287             (void)fflush(auxfi);
288         break;
289     case C_ABORT:
290         printf("Aborted\n");
291         if (auxfi)
292             fprintf(auxfi, "Aborted\n");
293         break;
294     case C_CMDERR:
295     case C_BADCMD:
296         printf("Error; ");
297         if (auxfi)
298             fprintf(auxfi, "Error; ");
299         break;
300     case C_EXIT:
301         printf("Exit: ");
302         if (auxfi)
303             fprintf(auxfi, "Exit: ");
304         break;
305     case C_FLASH:
306         printf("\n");
307         break;
308     default:
309         break;
310     }
311     if (auxfi) {
312         fprintf(auxfi, "%s", buf);
313         if (code == C_FLUSH)
314             (void)fflush(auxfi);
315     }
316
317     if (redir_fp)
318         fprintf(redir_fp, "%s", buf);
319     else if (pipe_fp)
320         fprintf(pipe_fp, "%s", buf);
321     else {
322         screen(buf);
323         if (code == C_FLUSH)
324             (void)fflush(stdout);
325     }
326 }
327
328 static void
329 screen(char *buf)
330 {
331     char c;
332
333     while ((c = *buf++)) {
334         if (eight_bit_clean) {
335             if (c == 14)
336                 putso();
337             else if (c == 15)
338                 putse();
339             else
340                 putchar(c);
341         } else if (c & 0x80) {
342             putso();
343             putchar(c & 0x7f);
344             putse();
345         } else
346             putchar(c);
347     }
348 }