]> git.pond.sub.org Git - empserver/blob - src/client/servcmd.c
Import of Empire 4.2.12
[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 <ctype.h>
42 #include <fcntl.h>
43 #if !defined(_WIN32)
44 #include <unistd.h>
45 #endif
46
47 extern s_char *gettag();
48
49 s_char  num_teles[64];
50 static  s_char  the_prompt[1024];
51 static  int     mode;
52 static  int     nbtu;
53 static  int     nmin;
54 FILE    *redir_fp;
55 FILE    *pipe_fp;
56 int     exec_fd;
57
58 void prompt();
59 void doredir();
60 void dopipe();
61 void doexecute();
62 void output();
63 void screen();
64 void free();
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 &&
119                                     !pipe_fp &&
120                                     !exec_fd) {
121                                         putchar('\07');
122                                         prompt(0);
123                                 }
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",name);
194                 return;
195         }
196         mode = O_WRONLY | O_CREAT;
197         if (how[1] == '>')
198                 mode |= O_APPEND;
199         else if (how[1] == '!')
200                 mode |= O_TRUNC;
201         else
202                 mode |= O_EXCL;
203         if (*name == 0) {
204                 fprintf(stderr, "Null file name after redirect\n");
205                 free(tag);
206                 return;
207         }
208         if ((fd = open(name, mode, 0600)) < 0) {
209                 fprintf(stderr, "Redirect open failed\n");
210                 perror(name);
211         } else {
212                 redir_fp = fdopen(fd, "w");
213         }
214         free(tag);
215 }
216
217 /*
218  * opens "pipe_fp" if successful
219  */
220 void
221 dopipe(p)
222         s_char  *p;
223 {
224         extern  FILE *popen();
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, "WARNING!  Server attempted unauthorized read of file %s\n",p);
266                 return;
267         }
268         if (p == 0) {
269                 fprintf(stderr, "Null file to execute\n");
270                 free(tag);
271                 return;
272         }
273 #if !defined(_WIN32)
274         if ((fd = open(p, O_RDONLY, 0)) < 0) {
275 #else
276         if ((fd = open(p, O_RDONLY|O_BINARY, 0)) < 0) {
277 #endif
278                 fprintf(stderr, "Can't open execute file\n");
279                 perror(p);
280                 free(tag);
281                 return;
282         }
283         /* copies 4k at a time to the socket */
284         while (termio(fd, sock, auxfi)) /*do copy*/;
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                                 ;
367                         (void) putc(c & 0x7f, stdout);
368                         for (sop = SE; putc(*sop, stdout); sop++)
369                                 ;
370                 } else
371                         (void) putc(c, stdout);
372         }
373 }