225 lines
5.8 KiB
C
225 lines
5.8 KiB
C
/***********************************************************************/
|
|
/* */
|
|
/* Objective Caml */
|
|
/* */
|
|
/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
|
|
/* */
|
|
/* Copyright 1996 Institut National de Recherche en Informatique et */
|
|
/* en Automatique. All rights reserved. This file is distributed */
|
|
/* under the terms of the GNU Library General Public License. */
|
|
/* */
|
|
/***********************************************************************/
|
|
|
|
/* $Id$ */
|
|
|
|
/* Win32-specific stuff */
|
|
|
|
#include <windows.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <io.h>
|
|
#include <fcntl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include "signals.h"
|
|
|
|
/* Path searching function */
|
|
|
|
char * searchpath(char * name)
|
|
{
|
|
#define MAX_PATH_LENGTH 1024
|
|
static char fullname[MAX_PATH_LENGTH];
|
|
char * filepart;
|
|
|
|
if (SearchPath(NULL, /* use system search path */
|
|
name,
|
|
".exe", /* add .exe extension if needed */
|
|
MAX_PATH_LENGTH, /* size of buffer */
|
|
fullname,
|
|
&filepart))
|
|
return fullname;
|
|
else
|
|
return name;
|
|
}
|
|
|
|
/* Expansion of @responsefile and *? file patterns in the command line */
|
|
|
|
static int argc;
|
|
static char ** argv;
|
|
static int argvsize;
|
|
|
|
static void store_argument(char * arg);
|
|
static void expand_argument(char * arg);
|
|
static void expand_pattern(char * arg);
|
|
static void expand_diversion(char * filename);
|
|
|
|
static void out_of_memory(void)
|
|
{
|
|
fprintf(stderr, "Out of memory while expanding command line\n");
|
|
exit(2);
|
|
}
|
|
|
|
static void store_argument(char * arg)
|
|
{
|
|
if (argc + 1 >= argvsize) {
|
|
argvsize *= 2;
|
|
argv = (char **) realloc(argv, argvsize * sizeof(char *));
|
|
if (argv == NULL) out_of_memory();
|
|
}
|
|
argv[argc++] = arg;
|
|
}
|
|
|
|
static void expand_argument(char * arg)
|
|
{
|
|
char * p;
|
|
|
|
if (arg[0] == '@') {
|
|
expand_diversion(arg + 1);
|
|
return;
|
|
}
|
|
for (p = arg; *p != 0; p++) {
|
|
if (*p == '*' || *p == '?') {
|
|
expand_pattern(arg);
|
|
return;
|
|
}
|
|
}
|
|
store_argument(arg);
|
|
}
|
|
|
|
static void expand_pattern(char * pat)
|
|
{
|
|
int handle;
|
|
struct _finddata_t ffblk;
|
|
|
|
handle = _findfirst(pat, &ffblk);
|
|
if (handle == -1) {
|
|
store_argument(pat); /* a la Bourne shell */
|
|
return;
|
|
}
|
|
do {
|
|
store_argument(strdup(ffblk.name));
|
|
} while (_findnext(handle, &ffblk) != -1);
|
|
_findclose(handle);
|
|
}
|
|
|
|
static void expand_diversion(char * filename)
|
|
{
|
|
struct _stat stat;
|
|
int fd;
|
|
char * buf, * endbuf, * p, * s;
|
|
|
|
if (_stat(filename, &stat) == -1 ||
|
|
(fd = _open(filename, O_RDONLY | O_BINARY, 0)) == -1) {
|
|
fprintf(stderr, "Cannot open file %s\n", filename);
|
|
exit(2);
|
|
}
|
|
buf = (char *) malloc(stat.st_size + 1);
|
|
if (buf == NULL) out_of_memory();
|
|
_read(fd, buf, stat.st_size);
|
|
endbuf = buf + stat.st_size;
|
|
_close(fd);
|
|
for (p = buf; p < endbuf; /*nothing*/) {
|
|
/* Skip leading blanks */
|
|
while (p < endbuf && isspace(*p)) p++;
|
|
if (p >= endbuf) break;
|
|
s = p;
|
|
/* Skip to next blank or end of buffer */
|
|
while (p < endbuf && !isspace(*p)) p++;
|
|
/* Delimit argument and expand it */
|
|
*p++ = 0;
|
|
expand_argument(s);
|
|
}
|
|
}
|
|
|
|
void expand_command_line(int * argcp, char *** argvp)
|
|
{
|
|
int i;
|
|
argc = 0;
|
|
argvsize = 16;
|
|
argv = (char **) malloc(argvsize * sizeof(char *));
|
|
if (argv == NULL) out_of_memory();
|
|
for (i = 0; i < *argcp; i++) expand_argument((*argvp)[i]);
|
|
argv[argc] = NULL;
|
|
*argcp = argc;
|
|
*argvp = argv;
|
|
}
|
|
|
|
/* Wrapper around "system" for Win32. Create a diversion file if
|
|
command line is too long. */
|
|
|
|
extern char * mktemp(char *);
|
|
|
|
int win32_system(char * cmdline)
|
|
{
|
|
#define MAX_CMD_LENGTH 256
|
|
char cmd[MAX_CMD_LENGTH + 16];
|
|
char template[9];
|
|
char * tempfile;
|
|
FILE * fd;
|
|
int len, i, j, k, retcode;
|
|
|
|
len = strlen(cmdline);
|
|
if (len < 1000) {
|
|
return system(cmdline);
|
|
} else {
|
|
/* Skip initial blanks, if any */
|
|
for (i = 0; cmdline[i] != 0 && isspace(cmdline[i]); i++) /*nothing*/;
|
|
/* Copy command name to buffer, stop at first blank */
|
|
for (j = 0; cmdline[i] != 0 && ! isspace(cmdline[i]); i++) {
|
|
if (j < MAX_CMD_LENGTH) cmd[j++] = cmdline[i];
|
|
}
|
|
/* Save remainder of command line to temp file */
|
|
strcpy(template, "cmXXXXXX");
|
|
tempfile = mktemp(template);
|
|
fd = fopen(tempfile, "w");
|
|
if (fd == NULL) return -1;
|
|
for (k = i; k < len; k++)
|
|
fputc((isspace(cmdline[k]) ? '\n' : cmdline[k]), fd);
|
|
fclose(fd);
|
|
/* Add " @tempfile" to the command line */
|
|
sprintf(cmd + j, " @%s", tempfile);
|
|
/* Run command */
|
|
retcode = system(cmd);
|
|
/* Remove temp file and exit */
|
|
unlink(tempfile);
|
|
return retcode;
|
|
}
|
|
}
|
|
|
|
/* Set up a new thread for control-C emulation */
|
|
|
|
#define hexa_digit(ch) (ch >= 97 ? ch - 87 : \
|
|
(ch >= 65 ? ch - 55 : \
|
|
(ch >= 48 ? ch - 48 : 0)))
|
|
|
|
DWORD WINAPI caml_signal_thread(LPVOID lpParam)
|
|
{
|
|
char *data;
|
|
int i;
|
|
HANDLE h;
|
|
/* Get an hexa-code raw handle through the environment */
|
|
data = getenv("CAMLSIGPIPE");
|
|
for(i = 0; i < sizeof(HANDLE); i++)
|
|
((char*)&h)[i] = (hexa_digit(data[2*i]) << 4) + hexa_digit(data[2*i+1]);
|
|
while (1) {
|
|
DWORD numread;
|
|
BOOL ret;
|
|
char iobuf[2];
|
|
/* This shall always return a single character */
|
|
ret = ReadFile(h, iobuf, 1, &numread, NULL);
|
|
if (!ret || numread != 1) sys_exit(Val_int(0));
|
|
switch (iobuf[0]) {
|
|
case 'C':
|
|
pending_signal = SIGINT;
|
|
something_to_do = 1;
|
|
break;
|
|
case 'T':
|
|
exit(0);
|
|
break;
|
|
}
|
|
}
|
|
}
|