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