00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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 }