00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "pex-common.h"
00023
00024 #include <stdio.h>
00025 #include <errno.h>
00026 #ifdef NEED_DECLARATION_ERRNO
00027 extern int errno;
00028 #endif
00029 #ifdef HAVE_STRING_H
00030 #include <string.h>
00031 #endif
00032 #ifdef HAVE_STDLIB_H
00033 #include <stdlib.h>
00034 #endif
00035
00036 #include "safe-ctype.h"
00037 #include <process.h>
00038
00039
00040
00041 #define PEX_MSDOS_FILE_COUNT 3
00042
00043 #define PEX_MSDOS_FD_OFFSET 10
00044
00045 struct pex_msdos
00046 {
00047
00048
00049 const char *files[PEX_MSDOS_FILE_COUNT];
00050
00051 int *statuses;
00052 };
00053
00054 static int pex_msdos_open (struct pex_obj *, const char *, int);
00055 static int pex_msdos_open (struct pex_obj *, const char *, int);
00056 static int pex_msdos_fdindex (struct pex_msdos *, int);
00057 static long pex_msdos_exec_child (struct pex_obj *, int, const char *,
00058 char * const *, char * const *,
00059 int, int, int, int,
00060 int, const char **, int *);
00061 static int pex_msdos_close (struct pex_obj *, int);
00062 static int pex_msdos_wait (struct pex_obj *, long, int *, struct pex_time *,
00063 int, const char **, int *);
00064 static void pex_msdos_cleanup (struct pex_obj *);
00065
00066
00067
00068 const struct pex_funcs funcs =
00069 {
00070 pex_msdos_open,
00071 pex_msdos_open,
00072 pex_msdos_exec_child,
00073 pex_msdos_close,
00074 pex_msdos_wait,
00075 NULL,
00076 NULL,
00077 NULL,
00078 pex_msdos_cleanup
00079 };
00080
00081
00082
00083 struct pex_obj *
00084 pex_init (int flags, const char *pname, const char *tempbase)
00085 {
00086 struct pex_obj *ret;
00087 int i;
00088
00089
00090 flags &= ~ PEX_USE_PIPES;
00091
00092 ret = pex_init_common (flags, pname, tempbase, funcs);
00093
00094 ret->sysdep = XNEW (struct pex_msdos);
00095 for (i = 0; i < PEX_MSDOS_FILE_COUNT; ++i)
00096 ret->files[i] = NULL;
00097 ret->statuses = NULL;
00098
00099 return ret;
00100 }
00101
00102
00103
00104
00105 static int
00106 pex_msdos_open (struct pex_obj *obj, const char *name,
00107 int binary ATTRIBUTE_UNUSED)
00108 {
00109 struct pex_msdos *ms;
00110 int i;
00111
00112 ms = (struct pex_msdos *) obj->sysdep;
00113
00114 for (i = 0; i < PEX_MSDOS_FILE_COUNT; ++i)
00115 {
00116 if (ms->files[i] == NULL)
00117 {
00118 ms->files[i] = xstrdup (name);
00119 return i + PEX_MSDOS_FD_OFFSET;
00120 }
00121 }
00122
00123 abort ();
00124 }
00125
00126
00127
00128
00129 static int
00130 pex_msdos_fdindex (struct pex_msdos *ms, int fd)
00131 {
00132 fd -= PEX_MSDOS_FD_OFFSET;
00133 if (fd < 0 || fd >= PEX_MSDOS_FILE_COUNT || ms->files[fd] == NULL)
00134 abort ();
00135 return fd;
00136 }
00137
00138
00139
00140
00141 static int
00142 pex_msdos_close (struct pex_obj *obj, int fd)
00143 {
00144 struct pex_msdos *ms;
00145 int fdinex;
00146
00147 ms = (struct pex_msdos *) obj->sysdep;
00148 fdindex = pe_msdos_fdindex (ms, fd);
00149 free (ms->files[fdindex]);
00150 ms->files[fdindex] = NULL;
00151 }
00152
00153
00154
00155 static long
00156 pex_msdos_exec_child (struct pex_obj *obj, int flags, const char *executable,
00157 char * const * argv, char * const * env, int in, int out,
00158 int toclose ATTRIBUTE_UNUSED,
00159 int errdes ATTRIBUTE_UNUSED, const char **errmsg,
00160 int *err)
00161 {
00162 struct pex_msdos *ms;
00163 char *temp_base;
00164 int temp_base_allocated;
00165 char *rf;
00166 int inindex;
00167 char *infile;
00168 int outindex;
00169 char *outfile;
00170 char *scmd;
00171 FILE *argfile;
00172 int i;
00173 int status;
00174
00175 ms = (struct pex_msdos *) obj->sysdep;
00176
00177
00178
00179
00180 temp_base = obj->temp_base;
00181 if (temp_base != NULL)
00182 temp_base_allocated = 0;
00183 else
00184 {
00185 temp_base = choose_temp_base ();
00186 temp_base_allocated = 1;
00187 }
00188
00189 rf = concat (temp_base, ".gp", NULL);
00190
00191 if (temp_base_allocated)
00192 free (temp_base);
00193
00194 if (in == STDIN_FILE_NO)
00195 {
00196 inindex = -1;
00197 infile = "";
00198 }
00199 else
00200 {
00201 inindex = pex_msdos_fdindex (ms, in);
00202 infile = ms->files[inindex];
00203 }
00204
00205 if (out == STDOUT_FILE_NO)
00206 {
00207 outindex = -1;
00208 outfile = "";
00209 }
00210 else
00211 {
00212 outindex = pex_msdos_fdindex (ms, out);
00213 outfile = ms->files[outindex];
00214 }
00215
00216 scmd = XNEWVEC (char, strlen (program)
00217 + ((flags & PEXECUTE_SEARCH) != 0 ? 4 : 0)
00218 + strlen (rf)
00219 + strlen (infile)
00220 + strlen (outfile)
00221 + 10);
00222 sprintf (scmd, "%s%s @%s%s%s%s%s",
00223 program,
00224 (flags & PEXECUTE_SEARCH) != 0 ? ".exe" : "",
00225 rf,
00226 inindex != -1 ? " <" : "",
00227 infile,
00228 outindex != -1 ? " >" : "",
00229 outfile);
00230
00231 argfile = fopen (rf, "w");
00232 if (argfile == NULL)
00233 {
00234 *err = errno;
00235 free (scmd);
00236 free (rf);
00237 *errmsg = "cannot open temporary command file";
00238 return -1;
00239 }
00240
00241 for (i = 1; argv[i] != NULL; ++i)
00242 {
00243 char *p;
00244
00245 for (p = argv[i]; *p != '\0'; ++p)
00246 {
00247 if (*p == '"' || *p == '\'' || *p == '\\' || ISSPACE (*p))
00248 putc ('\\', argfile);
00249 putc (*p, argfile);
00250 }
00251 putc ('\n', argfile);
00252 }
00253
00254 fclose (argfile);
00255
00256 status = system (scmd);
00257
00258 if (status == -1)
00259 {
00260 *err = errno;
00261 remove (rf);
00262 free (scmd);
00263 free (rf);
00264 *errmsg = "system";
00265 return -1;
00266 }
00267
00268 remove (rf);
00269 free (scmd);
00270 free (rf);
00271
00272
00273
00274
00275 ms->statuses = XRESIZEVEC(int, ms->statuses, obj->count + 1);
00276 ms->statuses[obj->count] = status;
00277
00278 return obj->count;
00279 }
00280
00281
00282
00283
00284
00285 static int
00286 pex_msdos_wait (struct pex_obj *obj, long pid, int *status,
00287 struct pex_time *time, int done ATTRIBUTE_UNUSED,
00288 const char **errmsg ATTRIBUTE_UNUSED,
00289 int *err ATTRIBUTE_UNUSED)
00290 {
00291 struct pex_msdos *ms;
00292
00293 ms = (struct pex_msdos *) obj->sysdep;
00294
00295 if (time != NULL)
00296 memset (time, 0, sizeof *time);
00297
00298 *status = ms->statuses[pid];
00299
00300 return 0;
00301 }
00302
00303
00304
00305 static void
00306 pex_msdos_cleanup (struct pex_obj *obj)
00307 {
00308 struct pex_msdos *ms;
00309 int i;
00310
00311 ms = (struct pex_msdos *) obj->sysdep;
00312 for (i = 0; i < PEX_MSDOS_FILE_COUNT; ++i)
00313 if (msdos->files[i] != NULL)
00314 free (msdos->files[i]);
00315 if (msdos->statuses != NULL)
00316 free (msdos->statuses);
00317 free (msdos);
00318 obj->sysdep = NULL;
00319 }