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