]> git.pond.sub.org Git - empserver/blob - src/client/servcmd.c
0b837f3ebd464927fc43099addce610f8e63f82c
[empserver] / src / client / servcmd.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  *  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  *     Ron Koenderink, 2005
34  *     Markus Armbruster, 2005-2007
35  */
36
37 #include <config.h>
38
39 #include <assert.h>
40 #include <ctype.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include "misc.h"
46 #include "proto.h"
47 #include "secure.h"
48
49 int eight_bit_clean;
50 FILE *auxfp;
51
52 static FILE *redir_fp;
53 static FILE *pipe_fp;
54 static size_t input_to_forget;
55
56 static void prompt(int, char *, char *);
57 static void doredir(char *p);
58 static void dopipe(char *p);
59 static void doexecute(char *p);
60
61 void
62 servercmd(int code, char *arg, int len)
63 {
64     static int nmin, nbtu;
65     static char the_prompt[1024];
66     static char teles[64];
67
68     switch (code) {
69     case C_PROMPT:
70         if (sscanf(arg, "%d %d", &nmin, &nbtu) != 2) {
71             fprintf(stderr, "prompt: bad server prompt %s\n", arg);
72         }
73         snprintf(the_prompt, sizeof(the_prompt), "[%d:%d] Command : ",
74                  nmin, nbtu);
75         prompt(code, the_prompt, teles);
76         break;
77     case C_FLUSH:
78         snprintf(the_prompt, sizeof(the_prompt), "%.*s", len - 1, arg);
79         prompt(code, the_prompt, teles);
80         break;
81     case C_EXECUTE:
82         doexecute(arg);
83         break;
84     case C_EXIT:
85         printf("Exit: %s", arg);
86         if (auxfp)
87             fprintf(auxfp, "Exit: %s", arg);
88         break;
89     case C_FLASH:
90         printf("\n%s", arg);
91         if (auxfp)
92             fprintf(auxfp, "\n%s", arg);
93         break;
94     case C_INFORM:
95         if (*arg) {
96             snprintf(teles, sizeof(teles), "(%.*s )", len -1, arg);
97             if (!redir_fp && !pipe_fp) {
98                 putchar('\07');
99                 prompt(code, the_prompt, teles);
100             }
101         } else
102             teles[0] = 0;
103         break;
104     case C_PIPE:
105         dopipe(arg);
106         break;
107     case C_REDIR:
108         doredir(arg);
109         break;
110     default:
111         assert(0);
112         break;
113     }
114 }
115
116 static void
117 prompt(int code, char *prompt, char *teles)
118 {
119     char *nl;
120
121     if (code == C_PROMPT) {
122         if (redir_fp) {
123             (void)fclose(redir_fp);
124             redir_fp = NULL;
125         } else if (pipe_fp) {
126             (void)pclose(pipe_fp);
127             pipe_fp = NULL;
128         }
129         if (input_to_forget) {
130             forget_input(input_to_forget);
131             input_to_forget = 0;
132         }
133     }
134
135     nl = code == C_PROMPT || code == C_INFORM ? "\n" : "";
136     printf("%s%s%s", nl, teles, prompt);
137     fflush(stdout);
138     if (auxfp) {
139         fprintf(auxfp, "%s%s%s", nl, teles, prompt);
140         fflush(auxfp);
141     }
142 }
143
144 static char *
145 fname(char *s)
146 {
147     char *beg, *end;
148
149     for (beg = s; isspace(*(unsigned char *)beg); beg++) ;
150     for (end = beg; !isspace(*(unsigned char *)end); end++) ;
151     *end = 0;
152     return beg;
153 }
154
155 static int
156 redir_authorized(char *arg, char *attempt)
157 {
158     size_t seen = seen_input(arg);
159
160     if (!seen || (input_to_forget && input_to_forget != seen)) {
161         fprintf(stderr, "WARNING!  Server attempted to %s %s\n",
162                 attempt, arg);
163         return 0;
164     }
165     input_to_forget = seen;
166     return 1;
167 }
168
169 /*
170  * opens redir_fp if successful
171  */
172 static void
173 doredir(char *p)
174 {
175     int mode;
176     int fd;
177
178     if (redir_fp) {
179         (void)fclose(redir_fp);
180         redir_fp = NULL;
181     }
182
183     if (!redir_authorized(p, "redirect to file"))
184         return;
185     if (*p++ != '>') {
186         fprintf(stderr, "WARNING!  Weird redirection %s", p);
187         return;
188     }
189
190     mode = O_WRONLY | O_CREAT;
191     if (*p == '>') {
192         mode |= O_APPEND;
193         p++;
194     } else if (*p == '!') {
195         mode |= O_TRUNC;
196         p++;
197     } else
198         mode |= O_EXCL;
199
200     p = fname(p);
201     if (*p == 0) {
202         fprintf(stderr, "Redirection lacks a file name\n");
203         return;
204     }
205
206     fd = open(p, mode, 0666);
207     redir_fp = fd < 0 ? NULL : fdopen(fd, "w");
208     if (!redir_fp) {
209         fprintf(stderr, "Can't redirect to %s: %s\n",
210                 p, strerror(errno));
211     }
212 }
213
214 /*
215  * opens "pipe_fp" if successful
216  */
217 static void
218 dopipe(char *p)
219 {
220     if (!redir_authorized(p, "pipe to command"))
221         return;
222     if (*p++ != '|') {
223         fprintf(stderr, "WARNING!  Weird pipe %s", p);
224         return;
225     }
226
227     for (; *p && isspace(*p); p++) ;
228     if (*p == 0) {
229         fprintf(stderr, "Redirection lacks a command\n");
230         return;
231     }
232
233     if ((pipe_fp = popen(p, "w")) == NULL) {
234         fprintf(stderr, "Can't redirect to pipe %s: %s\n",
235                 p, strerror(errno));
236     }
237 }
238
239 static void
240 doexecute(char *p)
241 {
242     input_fd = -1;              /* make sure play() terminates exec */
243
244     if (!redir_authorized(p, "read file"))
245         return;
246
247     p = fname(p);
248     if (*p == 0) {
249         fprintf(stderr, "Need a file to execute\n");
250         return;
251     }
252
253     if ((input_fd = open(p, O_RDONLY)) < 0) {
254         fprintf(stderr, "Can't open execute file %s: %s\n",
255                 p, strerror(errno));
256         return;
257     }
258 }
259
260 void
261 outch(char c)
262 {
263     if (auxfp)
264         putc(c, auxfp);
265     if (redir_fp)
266         putc(c, redir_fp);
267     else if (pipe_fp)
268         putc(c, pipe_fp);
269     else if (eight_bit_clean) {
270         if (c == 14)
271             putso();
272         else if (c == 15)
273             putse();
274         else
275             putchar(c);
276     } else if (c & 0x80) {
277         putso();
278         putchar(c & 0x7f);
279         putse();
280     } else
281         putchar(c);
282 }