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