src/client/servcmd.c

Go to the documentation of this file.
00001 /*
00002  *  Empire - A multi-player, client/server Internet based war game.
00003  *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
00004  *                           Ken Stevens, Steve McClure
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  *  ---
00021  *
00022  *  See files README, COPYING and CREDITS in the root of the source
00023  *  tree for related information and legal notices.  It is expected
00024  *  that future projects/authors will amend these files as needed.
00025  *
00026  *  ---
00027  *
00028  *  servercmd.c: Change the state depending on the command from the server.
00029  * 
00030  *  Known contributors to this file:
00031  *     Dave Pare, 1989
00032  *     Steve McClure, 1998
00033  *     Ron Koenderink, 2005
00034  *     Markus Armbruster, 2005-2007
00035  */
00036 
00037 #include <config.h>
00038 
00039 #include <assert.h>
00040 #include <ctype.h>
00041 #include <errno.h>
00042 #include <fcntl.h>
00043 #include <stdio.h>
00044 #include <string.h>
00045 #include "misc.h"
00046 #include "proto.h"
00047 #include "secure.h"
00048 
00049 #ifdef _WIN32
00050     #define open(filename, flags, ...) \
00051         ((flags & O_CREAT) \
00052          ? w32_openfd((filename), (flags), ## __VA_ARGS__) \
00053          : w32_openhandle((filename), (flags)))
00054 #endif
00055 
00056 int eight_bit_clean;
00057 FILE *auxfp;
00058 
00059 static FILE *redir_fp;
00060 static int redir_is_pipe;
00061 static int executing;
00062 static size_t input_to_forget;
00063 
00064 static void prompt(int, char *, char *);
00065 static void doredir(char *p);
00066 static void dopipe(char *p);
00067 static int doexecute(char *p);
00068 
00069 void
00070 servercmd(int code, char *arg, int len)
00071 {
00072     static int nmin, nbtu, fd;
00073     static char the_prompt[1024];
00074     static char teles[64];
00075 
00076     switch (code) {
00077     case C_PROMPT:
00078         if (sscanf(arg, "%d %d", &nmin, &nbtu) != 2) {
00079             fprintf(stderr, "prompt: bad server prompt %s\n", arg);
00080         }
00081         snprintf(the_prompt, sizeof(the_prompt), "[%d:%d] Command : ",
00082                  nmin, nbtu);
00083         if (redir_fp) {
00084             if (redir_is_pipe)
00085                 (void)pclose(redir_fp);
00086             else
00087                 (void)fclose(redir_fp);
00088             redir_fp = NULL;
00089         }
00090         if (input_to_forget) {
00091             forget_input(input_to_forget);
00092             input_to_forget = 0;
00093         }
00094         prompt(code, the_prompt, teles);
00095         executing = 0;
00096         break;
00097     case C_FLUSH:
00098         snprintf(the_prompt, sizeof(the_prompt), "%.*s", len - 1, arg);
00099         prompt(code, the_prompt, teles);
00100         break;
00101     case C_EXECUTE:
00102         fd = doexecute(arg);
00103         if (fd < 0)
00104             send_eof++;
00105         else {
00106             input_fd = fd;
00107             executing = 1;
00108         }
00109         break;
00110     case C_EXIT:
00111         printf("Exit: %s", arg);
00112         if (auxfp)
00113             fprintf(auxfp, "Exit: %s", arg);
00114         break;
00115     case C_FLASH:
00116         printf("\n%s", arg);
00117         if (auxfp)
00118             fprintf(auxfp, "\n%s", arg);
00119         break;
00120     case C_INFORM:
00121         if (arg[0] != '\n') {
00122             snprintf(teles, sizeof(teles), "(%.*s) ", len -1, arg);
00123             if (!redir_fp) {
00124                 putchar('\07');
00125                 prompt(code, the_prompt, teles);
00126             }
00127         } else
00128             teles[0] = 0;
00129         break;
00130     case C_PIPE:
00131         dopipe(arg);
00132         break;
00133     case C_REDIR:
00134         doredir(arg);
00135         break;
00136     default:
00137         assert(0);
00138         break;
00139     }
00140 }
00141 
00142 static void
00143 prompt(int code, char *prompt, char *teles)
00144 {
00145     char *nl;
00146 
00147     nl = code == C_PROMPT || code == C_INFORM ? "\n" : "";
00148     printf("%s%s%s", nl, teles, prompt);
00149     fflush(stdout);
00150     if (auxfp) {
00151         fprintf(auxfp, "%s%s%s", nl, teles, prompt);
00152         fflush(auxfp);
00153     }
00154 }
00155 
00156 static char *
00157 fname(char *s)
00158 {
00159     char *beg, *end;
00160 
00161     for (beg = s; isspace(*(unsigned char *)beg); beg++) ;
00162     for (end = beg; !isspace(*(unsigned char *)end); end++) ;
00163     *end = 0;
00164     return beg;
00165 }
00166 
00167 static int
00168 redir_authorized(char *arg, char *attempt, int expected)
00169 {
00170     size_t seen = seen_input(arg);
00171 
00172     if (executing) {
00173         fprintf(stderr, "Can't %s in a batch file\n", attempt);
00174         return 0;
00175     }
00176 
00177     if (!expected) {
00178         fprintf(stderr, "WARNING!  Server attempted to %s unexpectedly\n",
00179                 attempt);
00180         return 0;
00181     }
00182 
00183     if (!seen || (input_to_forget && input_to_forget != seen)) {
00184         fprintf(stderr, "WARNING!  Server attempted to %s %s\n",
00185                 attempt, arg);
00186         return 0;
00187     }
00188     input_to_forget = seen;
00189     return 1;
00190 }
00191 
00192 static void
00193 doredir(char *p)
00194 {
00195     int mode;
00196     int fd;
00197 
00198     if (!redir_authorized(p, "redirect to file", !redir_fp))
00199         return;
00200     if (*p++ != '>') {
00201         fprintf(stderr, "WARNING!  Weird redirection %s", p);
00202         return;
00203     }
00204 
00205     mode = O_WRONLY | O_CREAT;
00206     if (*p == '>') {
00207         mode |= O_APPEND;
00208         p++;
00209     } else if (*p == '!') {
00210         mode |= O_TRUNC;
00211         p++;
00212     } else
00213         mode |= O_EXCL;
00214 
00215     p = fname(p);
00216     if (*p == 0) {
00217         fprintf(stderr, "Redirection lacks a file name\n");
00218         return;
00219     }
00220 
00221     redir_is_pipe = 0;
00222     fd = open(p, mode, 0666);
00223     redir_fp = fd < 0 ? NULL : fdopen(fd, "w");
00224     if (!redir_fp) {
00225         fprintf(stderr, "Can't redirect to %s: %s\n",
00226                 p, strerror(errno));
00227     }
00228 }
00229 
00230 static void
00231 dopipe(char *p)
00232 {
00233     if (!redir_authorized(p, "pipe to shell command", !redir_fp))
00234         return;
00235     if (*p++ != '|') {
00236         fprintf(stderr, "WARNING!  Weird pipe %s", p);
00237         return;
00238     }
00239 
00240     for (; *p && isspace(*p); p++) ;
00241     if (*p == 0) {
00242         fprintf(stderr, "Redirection lacks a command\n");
00243         return;
00244     }
00245 
00246     redir_is_pipe = 1;
00247     if ((redir_fp = popen(p, "w")) == NULL) {
00248         fprintf(stderr, "Can't redirect to pipe %s: %s\n",
00249                 p, strerror(errno));
00250     }
00251 }
00252 
00253 static int
00254 doexecute(char *p)
00255 {
00256     int fd;
00257 
00258     if (!redir_authorized(p, "execute batch file", 1))
00259         return -1;
00260 
00261     p = fname(p);
00262     if (*p == 0) {
00263         fprintf(stderr, "Need a file to execute\n");
00264         return -1;
00265     }
00266 
00267     if ((fd = open(p, O_RDONLY)) < 0) {
00268         fprintf(stderr, "Can't open execute file %s: %s\n",
00269                 p, strerror(errno));
00270         return -1;
00271     }
00272 
00273     return fd;
00274 }
00275 
00276 void
00277 outch(char c)
00278 {
00279     if (auxfp)
00280         putc(c, auxfp);
00281     if (redir_fp)
00282         putc(c, redir_fp);
00283     else if (eight_bit_clean) {
00284         if (c == 14)
00285             putso();
00286         else if (c == 15)
00287             putse();
00288         else
00289             putchar(c);
00290     } else if (c & 0x80) {
00291         putso();
00292         putchar(c & 0x7f);
00293         putse();
00294     } else
00295         putchar(c);
00296 }

Generated on Fri Mar 28 11:01:11 2008 for empserver by  doxygen 1.5.2