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