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