Add support for OS/2, contributed by Andreas Buening <andreas.buening@nexgo.de>

Also a small patch from Hartmut Becker <Hartmut.Becker@compaq.com> for VMS.
This commit is contained in:
Paul Smith 2003-03-24 23:14:15 +00:00
parent 1fa3db1468
commit 4068c5e4a3
12 changed files with 719 additions and 98 deletions

View File

@ -1,3 +1,52 @@
2003-02-25 Paul D. Smith <psmith@gnu.org>
Port to OS/2 (__EMX__) by Andreas Buening <andreas.buening@nexgo.de>.
* job.c (_is_unixy_shell) [OS/2]: New function.
Set default shell to /bin/sh.
(reap_children): Close the job_rfd pipe here since we don't use a
SIGCHLD handler.
(set_child_handler_action_flags): define this to empty on OS/2.
(start_job_command): Close the jobserver pipe and use
child_execute_job() instead of fork/exec.
(child_execute_job): Rewrite to handle stdin/stdout FDs and spawn
rather than exec'ing, then reconfigure stdin/stdout.
(exec_command): Rewrite to use spawn instead of exec. Return the
PID of the child.
* main.c (main) [OS/2]: Call initialize_main(). Handle argv[0] as
in DOS. Handle the TEMP environment variable as in DOS. Don't
use a SIGCHLD handler on OS/2. Choose a shell as in DOS. Don't
use -j in DOS mode. Use child_execute_job() instead of
exec_command().
* function.c (func_shell) [OS/2]: Can't use fork/exec on OS/2: use
spawn() instead.
* job.h [OS/2]: Move CLOSE_ON_EXEC here from job.c. Add
prototypes that return values.
* remake.c (f_mtime) [OS/2]: Handle FAT timestamp offsets for OS/2.
* read.c (readline) [OS/2]: Don't handle CRLF specially on OS/2.
* default.c (default_suffixes) [OS/2]: Set proper default suffixes
for OS/2.
* vpath.c (construct_vpath_list) [OS/2]: Handle OS/2 paths like
DOS paths.
2003-02-24 Paul D. Smith <psmith@gnu.org>
* default.c [VMS]: New default rules for .cxx -> .obj compiles.
* job.c (child_execute_job) [VMS]: New code for handling spawn().
(child_execute_job) [VMS]: Handle error status properly.
Patches provided by Hartmut Becker <Hartmut.Becker@compaq.com>.
* function.c (func_shell): Use EINTRLOOP() while reading from the
subshell pipe (Fixes bug #2502).
* job.c (free_child): Use EINTRLOOP() while writing tokens to the
jobserver pipe.
* main.c (main): Ditto.
2003-01-30 Paul D. Smith <psmith@gnu.org> 2003-01-30 Paul D. Smith <psmith@gnu.org>
* read.c (eval): eval() was not fully reentrant, because the * read.c (eval): eval() was not fully reentrant, because the

View File

@ -27,8 +27,8 @@ Boston, MA 02111-1307, USA. */
/* Define GCC_IS_NATIVE if gcc is the native development environment on /* Define GCC_IS_NATIVE if gcc is the native development environment on
your system (gcc/bison/flex vs cc/yacc/lex). */ your system (gcc/bison/flex vs cc/yacc/lex). */
#ifdef __MSDOS__ #if defined(__MSDOS__) || defined(__EMX__)
#define GCC_IS_NATIVE # define GCC_IS_NATIVE
#endif #endif
@ -41,6 +41,10 @@ static char default_suffixes[]
= ".exe .olb .ln .obj .c .cxx .cc .pas .p .for .f .r .y .l .mar \ = ".exe .olb .ln .obj .c .cxx .cc .pas .p .for .f .r .y .l .mar \
.s .ss .i .ii .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \ .s .ss .i .ii .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
.w .ch .cweb .web .com .sh .elc .el"; .w .ch .cweb .web .com .sh .elc .el";
#elif defined(__EMX__)
= ".out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l .s .S \
.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
.w .ch .web .sh .elc .el .obj .exe .dll .lib";
#else #else
= ".out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l .s .S \ = ".out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l .s .S \
.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \ .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
@ -153,6 +157,8 @@ static char *default_suffix_rules[] =
"$(COMPILE.cc)/noprep/noobj/machine /list=$@ $<", "$(COMPILE.cc)/noprep/noobj/machine /list=$@ $<",
".cc.obj", ".cc.obj",
"$(COMPILE.cc) /obj=$@ $<", "$(COMPILE.cc) /obj=$@ $<",
".cxx.obj",
"$(COMPILE.cxx) /obj=$@ $<",
".for.obj", ".for.obj",
"$(COMPILE.for) /obj=$@ $<", "$(COMPILE.for) /obj=$@ $<",
".pas.obj", ".pas.obj",

4
dir.c
View File

@ -589,6 +589,10 @@ dir_contents_file_exists_p (struct directory_contents *dir, char *filename)
filename = downcase (filename); filename = downcase (filename);
#endif #endif
#ifdef __EMX__
_fnlwr(filename); /* lower case for FAT drives */
#endif
#ifdef VMS #ifdef VMS
filename = vmsify (filename,0); filename = vmsify (filename,0);
#endif #endif

View File

@ -1450,6 +1450,7 @@ func_shell (char *o, char **argv, const char *funcname)
error_prefix = ""; error_prefix = "";
#ifdef WINDOWS32 #ifdef WINDOWS32
windows32_openpipe (pipedes, &pid, command_argv, envp); windows32_openpipe (pipedes, &pid, command_argv, envp);
if (pipedes[0] < 0) { if (pipedes[0] < 0) {
@ -1458,31 +1459,46 @@ func_shell (char *o, char **argv, const char *funcname)
return o; return o;
} else } else
#else /* WINDOWS32 */
# ifdef __MSDOS__ #elif defined(__MSDOS__)
fpipe = msdos_openpipe (pipedes, &pid, argv[0]); fpipe = msdos_openpipe (pipedes, &pid, argv[0]);
if (pipedes[0] < 0) if (pipedes[0] < 0)
{ {
perror_with_name (error_prefix, "pipe"); perror_with_name (error_prefix, "pipe");
return o; return o;
} }
# else
#else
if (pipe (pipedes) < 0) if (pipe (pipedes) < 0)
{ {
perror_with_name (error_prefix, "pipe"); perror_with_name (error_prefix, "pipe");
return o; return o;
} }
# ifdef __EMX__
/* close some handles that are unnecessary for the child process */
CLOSE_ON_EXEC(pipedes[1]);
CLOSE_ON_EXEC(pipedes[0]);
/* Never use fork()/exec() here! Use spawn() instead in exec_command() */
pid = child_execute_job (0, pipedes[1], command_argv, envp);
if (pid < 0)
perror_with_name (error_prefix, "spawn");
# else /* ! __EMX__ */
pid = vfork (); pid = vfork ();
if (pid < 0) if (pid < 0)
perror_with_name (error_prefix, "fork"); perror_with_name (error_prefix, "fork");
else if (pid == 0) else if (pid == 0)
child_execute_job (0, pipedes[1], command_argv, envp); child_execute_job (0, pipedes[1], command_argv, envp);
else else
# endif /* ! __MSDOS__ */
#endif /* WINDOWS32 */ # endif
#endif
{ {
/* We are the parent. */ /* We are the parent. */
@ -1517,7 +1533,7 @@ func_shell (char *o, char **argv, const char *funcname)
buffer = (char *) xrealloc (buffer, maxlen + 1); buffer = (char *) xrealloc (buffer, maxlen + 1);
} }
cc = read (pipedes[0], &buffer[i], maxlen - i); EINTRLOOP (cc, read (pipedes[0], &buffer[i], maxlen - i));
if (cc <= 0) if (cc <= 0)
break; break;
} }
@ -1531,8 +1547,8 @@ func_shell (char *o, char **argv, const char *funcname)
(void) close (pipedes[0]); (void) close (pipedes[0]);
#endif #endif
/* Loop until child_handler sets shell_function_completed /* Loop until child_handler or reap_children() sets
to the status of our child shell. */ shell_function_completed to the status of our child shell. */
while (shell_function_completed == 0) while (shell_function_completed == 0)
reap_children (1, 0); reap_children (1, 0);

515
job.c
View File

@ -32,31 +32,43 @@ Boston, MA 02111-1307, USA. */
/* Default shell to use. */ /* Default shell to use. */
#ifdef WINDOWS32 #ifdef WINDOWS32
char *default_shell = "sh.exe"; char *default_shell = "sh.exe";
int no_default_sh_exe = 1; int no_default_sh_exe = 1;
int batch_mode_shell = 1; int batch_mode_shell = 1;
#else /* WINDOWS32 */
# ifdef _AMIGA #elif defined (_AMIGA)
char default_shell[] = ""; char default_shell[] = "";
extern int MyExecute (char **); extern int MyExecute (char **);
# else /* _AMIGA */ int batch_mode_shell = 0;
# ifdef __MSDOS__
#elif defined (__MSDOS__)
/* The default shell is a pointer so we can change it if Makefile /* The default shell is a pointer so we can change it if Makefile
says so. It is without an explicit path so we get a chance says so. It is without an explicit path so we get a chance
to search the $PATH for it (since MSDOS doesn't have standard to search the $PATH for it (since MSDOS doesn't have standard
directories we could trust). */ directories we could trust). */
char *default_shell = "command.com"; char *default_shell = "command.com";
# else /* __MSDOS__ */
# ifdef VMS
# include <descrip.h>
char default_shell[] = "";
# else
char default_shell[] = "/bin/sh";
# endif /* VMS */
# endif /* __MSDOS__ */
int batch_mode_shell = 0; int batch_mode_shell = 0;
# endif /* _AMIGA */
#endif /* WINDOWS32 */ #elif defined (__EMX__)
const char *default_shell = "/bin/sh";
int batch_mode_shell = 0;
#elif defined (VMS)
# include <descrip.h>
char default_shell[] = "";
int batch_mode_shell = 0;
#else
char default_shell[] = "/bin/sh";
int batch_mode_shell = 0;
#endif
#ifdef __MSDOS__ #ifdef __MSDOS__
# include <process.h> # include <process.h>
@ -91,9 +103,7 @@ static int amiga_batch_file;
# include "pathstuff.h" # include "pathstuff.h"
#endif /* WINDOWS32 */ #endif /* WINDOWS32 */
#ifdef HAVE_FCNTL_H #ifdef __EMX__
# include <fcntl.h>
#else
# include <sys/file.h> # include <sys/file.h>
#endif #endif
@ -157,17 +167,6 @@ extern int wait ();
#endif /* Don't have `union wait'. */ #endif /* Don't have `union wait'. */
/* How to set close-on-exec for a file descriptor. */
#if !defined F_SETFD
# define CLOSE_ON_EXEC(_d)
#else
# ifndef FD_CLOEXEC
# define FD_CLOEXEC 1
# endif
# define CLOSE_ON_EXEC(_d) (void) fcntl ((_d), F_SETFD, FD_CLOEXEC)
#endif
#ifdef VMS #ifdef VMS
static int vms_jobsefnmask = 0; static int vms_jobsefnmask = 0;
#endif /* !VMS */ #endif /* !VMS */
@ -228,11 +227,57 @@ int unixy_shell = 1;
/* /*
* The macro which references this function is defined in make.h. * The macro which references this function is defined in make.h.
*/ */
int w32_kill(int pid, int sig) int
w32_kill(int pid, int sig)
{ {
return ((process_kill(pid, sig) == TRUE) ? 0 : -1); return ((process_kill(pid, sig) == TRUE) ? 0 : -1);
} }
#endif /* WINDOWS32 */ #endif /* WINDOWS32 */
#ifdef __EMX__
/* returns whether path is assumed to be a unix like shell. */
int
_is_unixy_shell (const char *path)
{
/* list of non unix shells */
const char *known_os2shells[] = {
"cmd.exe",
"cmd",
"4os2.exe",
"4os2",
"4dos.exe",
"4dos",
"command.com",
"command",
NULL
};
/* find the rightmost '/' or '\\' */
const char *name = strrchr (path, '/');
const char *p = strrchr (path, '\\');
unsigned i;
if (name && p) /* take the max */
name = (name > p) ? name : p;
else if (p) /* name must be 0 */
name = p;
else if (!name) /* name and p must be 0 */
name = path;
if (*name == '/' || *name == '\\') name++;
i = 0;
while (known_os2shells[i] != NULL) {
if (stricmp (name, known_os2shells[i]) == 0) /* strcasecmp() */
return 0; /* not a unix shell */
i++;
}
/* in doubt assume a unix like shell */
return 1;
}
#endif /* __EMX__ */
/* Write an error message describing the exit status given in /* Write an error message describing the exit status given in
EXIT_CODE, EXIT_SIG, and COREDUMP, for the target TARGET_NAME. EXIT_CODE, EXIT_SIG, and COREDUMP, for the target TARGET_NAME.
@ -384,6 +429,7 @@ handle_apos (char *p)
static unsigned int dead_children = 0; static unsigned int dead_children = 0;
#ifndef __EMX__ /* Don't use SIGCHLD handler on OS/2. */
RETSIGTYPE RETSIGTYPE
child_handler (int sig) child_handler (int sig)
{ {
@ -397,7 +443,7 @@ child_handler (int sig)
DB (DB_JOBS, (_("Got a SIGCHLD; %u unreaped children.\n"), dead_children)); DB (DB_JOBS, (_("Got a SIGCHLD; %u unreaped children.\n"), dead_children));
} }
#endif /* !__EMX__ */
extern int shell_function_pid, shell_function_completed; extern int shell_function_pid, shell_function_completed;
@ -527,6 +573,18 @@ reap_children (int block, int err)
exit_code = WEXITSTATUS (status); exit_code = WEXITSTATUS (status);
exit_sig = WIFSIGNALED (status) ? WTERMSIG (status) : 0; exit_sig = WIFSIGNALED (status) ? WTERMSIG (status) : 0;
coredump = WCOREDUMP (status); coredump = WCOREDUMP (status);
#ifdef __EMX__
/* the SIGCHLD handler must not be used on OS/2 because, unlike
on UNIX systems, it had to call wait() itself. Therefore
job_rfd has to be closed here. */
if (job_rfd >= 0)
{
close (job_rfd);
job_rfd = -1;
}
#endif
} }
else else
{ {
@ -773,10 +831,12 @@ free_child (struct child *child)
if (job_fds[1] >= 0 && children) if (job_fds[1] >= 0 && children)
{ {
char token = '+'; char token = '+';
int r;
/* Write a job token back to the pipe. */ /* Write a job token back to the pipe. */
if (write (job_fds[1], &token, 1) != 1) EINTRLOOP (r, write (job_fds[1], &token, 1));
if (r != 1)
pfatal_with_name (_("write jobserver")); pfatal_with_name (_("write jobserver"));
DB (DB_JOBS, (_("Released token for child 0x%08lx (%s).\n"), DB (DB_JOBS, (_("Released token for child 0x%08lx (%s).\n"),
@ -832,6 +892,10 @@ unblock_sigs (void)
#endif #endif
#ifdef MAKE_JOBSERVER #ifdef MAKE_JOBSERVER
# ifdef __EMX__
/* Never install the SIGCHLD handler for EMX!!! */
# define set_child_handler_action_flags(x)
# else
/* Set the child handler action flags to FLAGS. */ /* Set the child handler action flags to FLAGS. */
static void static void
set_child_handler_action_flags (int flags) set_child_handler_action_flags (int flags)
@ -847,6 +911,7 @@ set_child_handler_action_flags (int flags)
sigaction (SIGCLD, &sa, NULL); sigaction (SIGCLD, &sa, NULL);
#endif #endif
} }
#endif /* !__EMX__ */
#endif #endif
@ -996,7 +1061,7 @@ start_job_command (struct child *child)
#if !defined(VMS) && !defined(_AMIGA) #if !defined(VMS) && !defined(_AMIGA)
if ( if (
#ifdef __MSDOS__ #if defined __MSDOS__ || defined (__EMX__)
unixy_shell /* the test is complicated and we already did it */ unixy_shell /* the test is complicated and we already did it */
#else #else
(argv[0] && !strcmp (argv[0], "/bin/sh")) (argv[0] && !strcmp (argv[0], "/bin/sh"))
@ -1119,6 +1184,40 @@ start_job_command (struct child *child)
#else #else
parent_environ = environ; parent_environ = environ;
# ifdef __EMX__
/* If we aren't running a recursive command and we have a jobserver
pipe, close it before exec'ing. */
if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
{
CLOSE_ON_EXEC (job_fds[0]);
CLOSE_ON_EXEC (job_fds[1]);
}
if (job_rfd >= 0)
CLOSE_ON_EXEC (job_rfd);
/* Never use fork()/exec() here! Use spawn() instead in exec_command() */
child->pid = child_execute_job (child->good_stdin ? 0 : bad_stdin, 1,
argv, child->environment);
if (child->pid < 0)
{
/* spawn failed! */
unblock_sigs ();
perror_with_name ("spawn", "");
goto error;
}
/* undo CLOSE_ON_EXEC() after the child process has been started */
if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
{
fcntl (job_fds[0], F_SETFD, 0);
fcntl (job_fds[1], F_SETFD, 0);
}
if (job_rfd >= 0)
fcntl (job_rfd, F_SETFD, 0);
#else /* !__EMX__ */
child->pid = vfork (); child->pid = vfork ();
environ = parent_environ; /* Restore value child may have clobbered. */ environ = parent_environ; /* Restore value child may have clobbered. */
if (child->pid == 0) if (child->pid == 0)
@ -1146,6 +1245,7 @@ start_job_command (struct child *child)
perror_with_name ("vfork", ""); perror_with_name ("vfork", "");
goto error; goto error;
} }
# endif /* !__EMX__ */
#endif /* !VMS */ #endif /* !VMS */
} }
@ -2175,10 +2275,13 @@ child_execute_job (char *argv, struct child *child)
&child->pid, &child->cstatus, &child->efn, &child->pid, &child->cstatus, &child->efn,
0, 0, 0, 0,
0, 0, 0); 0, 0, 0);
pidToAbort= child->pid; if (status & 1)
status= sys$waitfr (child->efn); {
pidToAbort= 0; pidToAbort= child->pid;
vmsHandleChildTerm(child); status= sys$waitfr (child->efn);
pidToAbort= 0;
vmsHandleChildTerm(child);
}
#else #else
status = lib$spawn (&cmddsc, status = lib$spawn (&cmddsc,
(ifiledsc.dsc$w_length == 0)?0:&ifiledsc, (ifiledsc.dsc$w_length == 0)?0:&ifiledsc,
@ -2194,6 +2297,14 @@ child_execute_job (char *argv, struct child *child)
{ {
printf (_("Error spawning, %d\n") ,status); printf (_("Error spawning, %d\n") ,status);
fflush (stdout); fflush (stdout);
switch (status)
{
case 0x1c:
errno = EPROCLIM;
break;
default:
errno = EFAIL;
}
} }
if (comname && !ISDB (DB_JOBS)) if (comname && !ISDB (DB_JOBS))
@ -2204,12 +2315,60 @@ child_execute_job (char *argv, struct child *child)
#else /* !VMS */ #else /* !VMS */
#if !defined (_AMIGA) && !defined (__MSDOS__) /* EMX: Start a child process. This function returns the new pid. */
# if defined __MSDOS__ || defined __EMX__
int
child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp)
{
int pid;
/* stdin_fd == 0 means: nothing to do for stdin;
stdout_fd == 1 means: nothing to do for stdout */
int save_stdin = (stdin_fd != 0) ? dup (0) : 0;
int save_stdout = (stdout_fd != 1) ? dup (1): 1;
/* < 0 only if dup() failed */
if (save_stdin < 0)
fatal (NILF, _("could not duplicate stdin\n"));
if (save_stdout < 0)
fatal (NILF, _("could not duplicate stdout\n"));
/* Close unnecessary file handles for the child. */
if (save_stdin != 0)
CLOSE_ON_EXEC (save_stdin);
if (save_stdout != 1)
CLOSE_ON_EXEC (save_stdout);
/* Connect the pipes to the child process. */
if (stdin_fd != 0)
(void) dup2 (stdin_fd, 0);
if (stdout_fd != 1)
(void) dup2 (stdout_fd, 1);
/* stdin_fd and stdout_fd must be closed on exit because we are
still in the parent process */
if (stdin_fd != 0)
CLOSE_ON_EXEC (stdin_fd);
if (stdout_fd != 1)
CLOSE_ON_EXEC (stdout_fd);
/* Run the command. */
pid = exec_command (argv, envp);
/* Restore stdout/stdin of the parent process. */
if (stdin_fd != 0 && dup2 (save_stdin, 0) != 0)
fatal (NILF, _("restoring of stdin failed\n"));
if (stdout_fd != 1 && dup2 (save_stdout, 1) != 1)
fatal (NILF, _("restoring of stdout failed\n"));
return pid;
}
#elif !defined (_AMIGA) && !defined (__MSDOS__)
/* UNIX: /* UNIX:
Replace the current process with one executing the command in ARGV. Replace the current process with one executing the command in ARGV.
STDIN_FD and STDOUT_FD are used as the process's stdin and stdout; ENVP is STDIN_FD and STDOUT_FD are used as the process's stdin and stdout; ENVP is
the environment of the new program. This function does not return. */ the environment of the new program. This function does not return. */
void void
child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp) child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp)
{ {
@ -2233,7 +2392,12 @@ child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp)
/* Replace the current process with one running the command in ARGV, /* Replace the current process with one running the command in ARGV,
with environment ENVP. This function does not return. */ with environment ENVP. This function does not return. */
void /* EMX: This function returns the pid of the child process. */
# ifdef __EMX__
int
# else
void
# endif
exec_command (char **argv, char **envp) exec_command (char **argv, char **envp)
{ {
#ifdef VMS #ifdef VMS
@ -2301,13 +2465,33 @@ exec_command (char **argv, char **envp)
#else /* !WINDOWS32 */ #else /* !WINDOWS32 */
# ifdef __EMX__
int pid;
# endif
/* Be the user, permanently. */ /* Be the user, permanently. */
child_access (); child_access ();
# ifdef __EMX__
/* Run the program. */
pid = spawnvpe (P_NOWAIT, argv[0], argv, envp);
if (pid >= 0)
return pid;
/* the file might have a strange shell extension */
if (errno == ENOENT)
errno = ENOEXEC;
# else
/* Run the program. */ /* Run the program. */
environ = envp; environ = envp;
execvp (argv[0], argv); execvp (argv[0], argv);
# endif /* !__EMX__ */
switch (errno) switch (errno)
{ {
case ENOENT: case ENOENT:
@ -2321,7 +2505,14 @@ exec_command (char **argv, char **envp)
char **new_argv; char **new_argv;
int argc; int argc;
# ifdef __EMX__
/* Do not use $SHELL from the environment */
shell = lookup_variable ("SHELL", 5);
if (shell)
shell = shell->value;
# else
shell = getenv ("SHELL"); shell = getenv ("SHELL");
# endif
if (shell == 0) if (shell == 0)
shell = default_shell; shell = default_shell;
@ -2338,7 +2529,13 @@ exec_command (char **argv, char **envp)
--argc; --argc;
} }
# ifdef __EMX__
pid = spawnvpe (P_NOWAIT, shell, new_argv, envp);
if (pid >= 0)
break;
# else
execvp (shell, new_argv); execvp (shell, new_argv);
# endif
if (errno == ENOENT) if (errno == ENOENT)
error (NILF, _("%s: Shell program not found"), shell); error (NILF, _("%s: Shell program not found"), shell);
else else
@ -2346,12 +2543,23 @@ exec_command (char **argv, char **envp)
break; break;
} }
# ifdef __EMX__
case EINVAL:
/* this nasty error was driving me nuts :-( */
error (NILF, _("spawnvpe: environment space might be exhausted"));
/* FALLTHROUGH */
# endif
default: default:
perror_with_name ("execvp: ", argv[0]); perror_with_name ("execvp: ", argv[0]);
break; break;
} }
# ifdef __EMX__
return pid;
# else
_exit (127); _exit (127);
# endif
#endif /* !WINDOWS32 */ #endif /* !WINDOWS32 */
#endif /* !VMS */ #endif /* !VMS */
} }
@ -2428,16 +2636,43 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
char *sh_chars; char *sh_chars;
char **sh_cmds; char **sh_cmds;
#else #elif defined (__EMX__)
#ifdef _AMIGA static char sh_chars_dos[] = "*?[];|<>%^&()";
static char *sh_cmds_dos[] = { "break", "call", "cd", "chcp", "chdir", "cls",
"copy", "ctty", "date", "del", "dir", "echo",
"erase", "exit", "for", "goto", "if", "md",
"mkdir", "path", "pause", "prompt", "rd",
"rmdir", "rem", "ren", "rename", "set",
"shift", "time", "type", "ver", "verify",
"vol", ":", 0 };
static char sh_chars_os2[] = "*?[];|<>%^()\"'&";
static char *sh_cmds_os2[] = { "call", "cd", "chcp", "chdir", "cls", "copy",
"date", "del", "detach", "dir", "echo",
"endlocal", "erase", "exit", "for", "goto", "if",
"keys", "md", "mkdir", "move", "path", "pause",
"prompt", "rd", "rem", "ren", "rename", "rmdir",
"set", "setlocal", "shift", "start", "time",
"type", "ver", "verify", "vol", ":", 0 };
static char sh_chars_sh[] = "#;\"*?[]&|<>(){}$`^";
static char *sh_cmds_sh[] = { "echo", "cd", "eval", "exec", "exit", "login",
"logout", "set", "umask", "wait", "while",
"for", "case", "if", ":", ".", "break",
"continue", "export", "read", "readonly",
"shift", "times", "trap", "switch", "unset",
0 };
char *sh_chars;
char **sh_cmds;
#elif defined (_AMIGA)
static char sh_chars[] = "#;\"|<>()?*$`"; static char sh_chars[] = "#;\"|<>()?*$`";
static char *sh_cmds[] = { "cd", "eval", "if", "delete", "echo", "copy", static char *sh_cmds[] = { "cd", "eval", "if", "delete", "echo", "copy",
"rename", "set", "setenv", "date", "makedir", "rename", "set", "setenv", "date", "makedir",
"skip", "else", "endif", "path", "prompt", "skip", "else", "endif", "path", "prompt",
"unset", "unsetenv", "version", "unset", "unsetenv", "version",
0 }; 0 };
#else #elif defined (WINDOWS32)
#ifdef WINDOWS32
static char sh_chars_dos[] = "\"|&<>"; static char sh_chars_dos[] = "\"|&<>";
static char *sh_cmds_dos[] = { "break", "call", "cd", "chcp", "chdir", "cls", static char *sh_cmds_dos[] = { "break", "call", "cd", "chcp", "chdir", "cls",
"copy", "ctty", "date", "del", "dir", "echo", "copy", "ctty", "date", "del", "dir", "echo",
@ -2464,8 +2699,6 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
"case", "if", ":", ".", "break", "continue", "case", "if", ":", ".", "break", "continue",
"export", "read", "readonly", "shift", "times", "export", "read", "readonly", "shift", "times",
"trap", "switch", 0 }; "trap", "switch", 0 };
#endif /* WINDOWS32 */
#endif /* Amiga */
#endif /* __MSDOS__ */ #endif /* __MSDOS__ */
register int i; register int i;
register char *p; register char *p;
@ -2513,7 +2746,7 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
if (slow_flag) if (slow_flag)
goto slow; goto slow;
#else /* not WINDOWS32 */ #else /* not WINDOWS32 */
#ifdef __MSDOS__ #if defined (__MSDOS__) || defined (__EMX__)
else if (stricmp (shell, default_shell)) else if (stricmp (shell, default_shell))
{ {
extern int _is_unixy_shell (const char *_path); extern int _is_unixy_shell (const char *_path);
@ -2521,6 +2754,10 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
message (1, _("$SHELL changed (was `%s', now `%s')"), default_shell, shell); message (1, _("$SHELL changed (was `%s', now `%s')"), default_shell, shell);
unixy_shell = _is_unixy_shell (shell); unixy_shell = _is_unixy_shell (shell);
default_shell = shell; default_shell = shell;
/* we must allocate a copy of shell: construct_command_argv() will free
* shell after this function returns. */
default_shell = xmalloc (strlen (shell) + 1);
strcpy (default_shell, shell);
} }
if (unixy_shell) if (unixy_shell)
{ {
@ -2531,11 +2768,17 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
{ {
sh_chars = sh_chars_dos; sh_chars = sh_chars_dos;
sh_cmds = sh_cmds_dos; sh_cmds = sh_cmds_dos;
} # ifdef __EMX__
#else /* not __MSDOS__ */ if (_osmode == OS2_MODE)
{
sh_chars = sh_chars_os2;
sh_cmds = sh_cmds_os2;
}
# endif
#else /* !__MSDOS__ */
else if (strcmp (shell, default_shell)) else if (strcmp (shell, default_shell))
goto slow; goto slow;
#endif /* not __MSDOS__ */ #endif /* !__MSDOS__ && !__EMX__ */
#endif /* not WINDOWS32 */ #endif /* not WINDOWS32 */
if (ifs != 0) if (ifs != 0)
@ -2838,6 +3081,11 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
+ (line_len * 2) + 1); + (line_len * 2) + 1);
char *command_ptr = NULL; /* used for batch_mode_shell mode */ char *command_ptr = NULL; /* used for batch_mode_shell mode */
# ifdef __EMX__ /* is this necessary? */
if (!unixy_shell)
minus_c[1] = '/'; /* " /c " */
# endif
ap = new_line; ap = new_line;
bcopy (shell, ap, shell_len); bcopy (shell, ap, shell_len);
ap += shell_len; ap += shell_len;
@ -2951,18 +3199,118 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
new_argv = construct_command_argv_internal (new_line, (char **) NULL, new_argv = construct_command_argv_internal (new_line, (char **) NULL,
(char *) 0, (char *) 0, (char *) 0, (char *) 0,
(char **) 0); (char **) 0);
#ifdef __MSDOS__ # ifdef __EMX__
else if (!unixy_shell)
{
/* new_line is local, must not be freed therefore */
char *p, *q;
int quote;
size_t index;
size_t len;
/* handle quotes
We have to remove all double quotes and to split the line
into distinct arguments because of the strange handling
of builtin commands by cmd: 'echo "bla"' prints "bla"
(with quotes) while 'c:\bin\echo.exe "bla"' prints bla
(without quotes). Some programs like autoconf rely
on the second behaviour. */
len = strlen (new_line) + 1;
/* More than 1 arg per character is impossible. */
new_argv = (char **) xmalloc (len * sizeof (char *));
/* All the args can fit in a buffer as big as new_line is. */
new_argv[0] = (char *) xmalloc (len);
index = 0;
quote = 0;
q = new_line;
p = new_argv[index];
while(*q != '\0')
{
/* searching for closing quote */
if (quote)
{
if (*q == quote)
{
/* remove the quote */
while(*q == quote) /* do not ask */
q++;
quote = 0;
}
else /* normal character: copy it */
*p++ = *q++;
}
/* searching for opening quote */
else if (*q == '\"'
# ifndef NO_CMD_DEFAULT
|| *q == '\''
# endif
)
{
/* remove opening quote */
quote = *q;
while(*q == quote) /* do not ask */
q++;
}
/* spaces outside of a quoted string: remove them
and start a new argument */
else if (*q == ' ' || *q == '\t')
{
*p++ = '\0'; /* trailing '\0' for last argument */
/* remove all successive spaces */
do
{
q++;
}
while(*q == ' ' || *q == '\t');
/* start new argument */
index++;
new_argv[index] = p;
}
/* normal character (no space) outside a quoted string*/
else
*p++ = *q++;
} /* end while() */
*p = '\0'; /* trailing '\0' for the last argument */
new_argv[index + 1] = NULL;
# ifndef NO_CMD_DEFAULT
/* special case: echo x="y"
(e.g. autoconf uses this to determine whether make works)
this is pure idioty but cmd works this way:
if 'echo' and 'x="y"' are two different arguments cmd
will print '"x="y""' but if they are only one argument
cmd will print 'bla="blurb"' as it should be
note: if we do not allow cmd to be the default shell
we do not need this kind of voodoo */
if (index == 3 && strcasecmp(new_argv[2], "echo") == 0)
{
new_argv[2][4] = ' ';
new_argv[3] = NULL;
}
# endif
}
#elif defined(__MSDOS__)
else else
{ {
/* With MSDOS shells, we must construct the command line here /* With MSDOS shells, we must construct the command line here
instead of recursively calling ourselves, because we instead of recursively calling ourselves, because we
cannot backslash-escape the special characters (see above). */ cannot backslash-escape the special characters (see above). */
new_argv = (char **) xmalloc (sizeof (char *)); new_argv = (char **) xmalloc (sizeof (char *));
line_len = strlen (new_line) - shell_len - sizeof (minus_c) + 1; line_len = strlen (new_line) - shell_len - sizeof (minus_c) + 1;
new_argv[0] = xmalloc (line_len + 1); new_argv[0] = xmalloc (line_len + 1);
strncpy (new_argv[0], strncpy (new_argv[0],
new_line + shell_len + sizeof (minus_c) - 1, line_len); new_line + shell_len + sizeof (minus_c) - 1, line_len);
new_argv[0][line_len] = '\0'; new_argv[0][line_len] = '\0';
} }
#else #else
else else
@ -3049,10 +3397,55 @@ construct_command_argv (char *line, char **restp, struct file *file,
* is not confused. * is not confused.
*/ */
if (shell) { if (shell) {
char *p = w32ify(shell, 0); char *p = w32ify (shell, 0);
strcpy(shell, p); strcpy (shell, p);
} }
#endif #endif
#ifdef __EMX__
{
static const char *unixroot = NULL;
static const char *last_shell = "";
static int init = 0;
if (init == 0)
{
unixroot = getenv ("UNIXROOT");
/* unixroot must be NULL or not empty */
if (unixroot && unixroot[0] == '\0') unixroot = NULL;
init = 1;
}
/* if we have an unixroot drive and if shell is not default_shell
(which means it's either cmd.exe or the test has already been
performed) and if shell is an absolute path without drive letter,
try whether it exists e.g.: if "/bin/sh" does not exist use
"$UNIXROOT/bin/sh" instead. */
if (unixroot && shell && strcmp (shell, last_shell) != 0
&& (shell[0] == '/' || shell[0] == '\\'))
{
/* trying a new shell, check whether it exists */
size_t size = strlen (shell);
char *buf = xmalloc (size + 7);
memcpy (buf, shell, size);
memcpy (buf + size, ".exe", 5); /* including the trailing '\0' */
if (access (shell, F_OK) != 0 && access (buf, F_OK) != 0)
{
/* try the same for the unixroot drive */
memmove (buf + 2, buf, size + 5);
buf[0] = unixroot[0];
buf[1] = unixroot[1];
if (access (buf, F_OK) == 0)
/* we have found a shell! */
/* free(shell); */
shell = buf;
else
free (buf);
}
else
free (buf);
}
}
#endif __EMX__
ifs = allocated_variable_expand_for_file ("$(IFS)", file); ifs = allocated_variable_expand_for_file ("$(IFS)", file);
warn_undefined_variables_flag = save; warn_undefined_variables_flag = save;

21
job.h
View File

@ -20,6 +20,23 @@ Boston, MA 02111-1307, USA. */
#ifndef SEEN_JOB_H #ifndef SEEN_JOB_H
#define SEEN_JOB_H #define SEEN_JOB_H
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#else
# include <sys/file.h>
#endif
/* How to set close-on-exec for a file descriptor. */
#if !defined F_SETFD
# define CLOSE_ON_EXEC(_d)
#else
# ifndef FD_CLOEXEC
# define FD_CLOEXEC 1
# endif
# define CLOSE_ON_EXEC(_d) (void) fcntl ((_d), F_SETFD, FD_CLOEXEC)
#endif
/* Structure describing a running or dead child process. */ /* Structure describing a running or dead child process. */
struct child struct child
@ -57,11 +74,15 @@ extern void start_waiting_jobs PARAMS ((void));
extern char **construct_command_argv PARAMS ((char *line, char **restp, struct file *file, char** batch_file)); extern char **construct_command_argv PARAMS ((char *line, char **restp, struct file *file, char** batch_file));
#ifdef VMS #ifdef VMS
extern int child_execute_job PARAMS ((char *argv, struct child *child)); extern int child_execute_job PARAMS ((char *argv, struct child *child));
#elif defined(__EMX__)
extern int child_execute_job PARAMS ((int stdin_fd, int stdout_fd, char **argv, char **envp));
#else #else
extern void child_execute_job PARAMS ((int stdin_fd, int stdout_fd, char **argv, char **envp)); extern void child_execute_job PARAMS ((int stdin_fd, int stdout_fd, char **argv, char **envp));
#endif #endif
#ifdef _AMIGA #ifdef _AMIGA
extern void exec_command PARAMS ((char **argv)); extern void exec_command PARAMS ((char **argv));
#elif defined(__EMX__)
extern int exec_command PARAMS ((char **argv, char **envp));
#else #else
extern void exec_command PARAMS ((char **argv, char **envp)); extern void exec_command PARAMS ((char **argv, char **envp));
#endif #endif

61
main.c
View File

@ -37,6 +37,10 @@ MA 02111-1307, USA. */
#include <windows.h> #include <windows.h>
#include "pathstuff.h" #include "pathstuff.h"
#endif #endif
#ifdef __EMX__
# include <sys/types.h>
# include <sys/wait.h>
#endif
#if defined(MAKE_JOBSERVER) && defined(HAVE_FCNTL_H) #if defined(MAKE_JOBSERVER) && defined(HAVE_FCNTL_H)
# include <fcntl.h> # include <fcntl.h>
#endif #endif
@ -846,6 +850,9 @@ main (int argc, char **argv, char **envp)
no_default_sh_exe = 1; no_default_sh_exe = 1;
#endif #endif
/* Needed for OS/2 */
initialize_main(&argc, &argv);
default_goal_file = 0; default_goal_file = 0;
reading_file = 0; reading_file = 0;
@ -952,7 +959,7 @@ main (int argc, char **argv, char **envp)
#else #else
program = strrchr (argv[0], '/'); program = strrchr (argv[0], '/');
#endif #endif
#ifdef __MSDOS__ #if defined(__MSDOS__) || defined(__EMX__)
if (program == 0) if (program == 0)
program = strrchr (argv[0], '\\'); program = strrchr (argv[0], '\\');
else else
@ -1136,7 +1143,7 @@ main (int argc, char **argv, char **envp)
strneq(argv[0], "//", 2)) strneq(argv[0], "//", 2))
argv[0] = xstrdup(w32ify(argv[0],1)); argv[0] = xstrdup(w32ify(argv[0],1));
#else /* WINDOWS32 */ #else /* WINDOWS32 */
#ifdef __MSDOS__ #if defined (__MSDOS__) || defined (__EMX__)
if (strchr (argv[0], '\\')) if (strchr (argv[0], '\\'))
{ {
char *p; char *p;
@ -1325,7 +1332,7 @@ main (int argc, char **argv, char **envp)
#define DEFAULT_TMPFILE "GmXXXXXX" #define DEFAULT_TMPFILE "GmXXXXXX"
if (((tmpdir = getenv ("TMPDIR")) == NULL || *tmpdir == '\0') if (((tmpdir = getenv ("TMPDIR")) == NULL || *tmpdir == '\0')
#if defined __MSDOS__ || defined(WINDOWS32) #if defined (__MSDOS__) || defined (WINDOWS32) || defined (__EMX__)
/* These are also used commonly on these platforms. */ /* These are also used commonly on these platforms. */
&& ((tmpdir = getenv ("TEMP")) == NULL || *tmpdir == '\0') && ((tmpdir = getenv ("TEMP")) == NULL || *tmpdir == '\0')
&& ((tmpdir = getenv ("TMP")) == NULL || *tmpdir == '\0') && ((tmpdir = getenv ("TMP")) == NULL || *tmpdir == '\0')
@ -1376,6 +1383,7 @@ main (int argc, char **argv, char **envp)
} }
} }
#ifndef __EMX__ /* Don't use a SIGCHLD handler for OS/2 */
#if defined(MAKE_JOBSERVER) || !defined(HAVE_WAIT_NOHANG) #if defined(MAKE_JOBSERVER) || !defined(HAVE_WAIT_NOHANG)
/* Set up to handle children dying. This must be done before /* Set up to handle children dying. This must be done before
reading in the makefiles so that `shell' function calls will work. reading in the makefiles so that `shell' function calls will work.
@ -1398,6 +1406,7 @@ main (int argc, char **argv, char **envp)
bsd_signal (SIGCLD, child_handler); bsd_signal (SIGCLD, child_handler);
# endif # endif
} }
#endif
#endif #endif
/* Let the user send us SIGUSR1 to toggle the -d flag during the run. */ /* Let the user send us SIGUSR1 to toggle the -d flag during the run. */
@ -1448,7 +1457,7 @@ main (int argc, char **argv, char **envp)
} }
#endif /* WINDOWS32 */ #endif /* WINDOWS32 */
#ifdef __MSDOS__ #if defined (__MSDOS__) || defined (__EMX__)
/* We need to know what kind of shell we will be using. */ /* We need to know what kind of shell we will be using. */
{ {
extern int _is_unixy_shell (const char *_path); extern int _is_unixy_shell (const char *_path);
@ -1468,7 +1477,7 @@ main (int argc, char **argv, char **envp)
default_shell = shell_path; default_shell = shell_path;
} }
} }
#endif /* __MSDOS__ */ #endif /* __MSDOS__ || __EMX__ */
/* Decode switches again, in case the variables were set by the makefile. */ /* Decode switches again, in case the variables were set by the makefile. */
decode_env_switches ("MAKEFLAGS", 9); decode_env_switches ("MAKEFLAGS", 9);
@ -1476,8 +1485,12 @@ main (int argc, char **argv, char **envp)
decode_env_switches ("MFLAGS", 6); decode_env_switches ("MFLAGS", 6);
#endif #endif
#ifdef __MSDOS__ #if defined (__MSDOS__) || defined (__EMX__)
if (job_slots != 1) if (job_slots != 1
# ifdef __EMX__
&& _osmode != OS2_MODE /* turn off -j if we are in DOS mode */
# endif
)
{ {
error (NILF, error (NILF,
_("Parallel jobs (-j) are not supported on this platform.")); _("Parallel jobs (-j) are not supported on this platform."));
@ -1557,8 +1570,13 @@ main (int argc, char **argv, char **envp)
want job_slots to be 0 to indicate we're using the jobserver. */ want job_slots to be 0 to indicate we're using the jobserver. */
while (--job_slots) while (--job_slots)
if (write (job_fds[1], &c, 1) != 1) {
pfatal_with_name (_("init jobserver pipe")); int r;
EINTRLOOP (r, write (job_fds[1], &c, 1));
if (r != 1)
pfatal_with_name (_("init jobserver pipe"));
}
/* Fill in the jobserver_fds struct for our children. */ /* Fill in the jobserver_fds struct for our children. */
@ -1880,11 +1898,30 @@ main (int argc, char **argv, char **envp)
if (job_rfd >= 0) if (job_rfd >= 0)
close (job_rfd); close (job_rfd);
#ifndef _AMIGA #ifdef _AMIGA
exec_command (nargv, environ);
#else
exec_command (nargv); exec_command (nargv);
exit (0); exit (0);
#elif defined (__EMX__)
{
/* It is not possible to use execve() here because this
would cause the parent process to be terminated with
exit code 0 before the child process has been terminated.
Therefore it may be the best solution simply to spawn the
child process including all file handles and to wait for its
termination. */
int pid;
int status;
pid = child_execute_job(0, 1, nargv, environ);
/* is this loop really necessary? */
do {
pid = wait(&status);
} while(pid <= 0);
/* use the exit code of the child process */
exit(WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
}
#else
exec_command (nargv, environ);
#endif #endif
/* NOTREACHED */ /* NOTREACHED */

47
make.h
View File

@ -349,15 +349,12 @@ extern int strcmpi (const char *,const char *);
#define S_(msg1,msg2,num) ngettext (msg1,msg2,num) #define S_(msg1,msg2,num) ngettext (msg1,msg2,num)
/* Handle other OSs. */ /* Handle other OSs. */
#if defined(HAVE_DOS_PATHS)
#if defined(__MSDOS__) || defined(WINDOWS32)
# define PATH_SEPARATOR_CHAR ';' # define PATH_SEPARATOR_CHAR ';'
#elif defined(VMS)
# define PATH_SEPARATOR_CHAR ','
#else #else
# if defined(VMS) # define PATH_SEPARATOR_CHAR ':'
# define PATH_SEPARATOR_CHAR ','
# else
# define PATH_SEPARATOR_CHAR ':'
# endif
#endif #endif
#ifdef WINDOWS32 #ifdef WINDOWS32
@ -538,6 +535,42 @@ extern int handling_fatal_signal;
#include <dmalloc.h> #include <dmalloc.h>
#endif #endif
#ifndef initialize_main
# ifdef __EMX__
# define initialize_main(pargc, pargv) \
{ _wildcard(pargc, pargv); _response(pargc, pargv); }
# else
# define initialize_main(pargc, pargv)
# endif
#endif
#ifdef __EMX__
# if !HAVE_STRCASECMP
# define strcasecmp stricmp
# endif
# if !defined chdir
# define chdir _chdir2
# endif
# if !defined getcwd
# define getcwd _getcwd2
# endif
/* NO_CHDIR2 causes make not to use _chdir2() and _getcwd2() instead of
chdir() and getcwd(). This avoids some error messages for the
make testsuite but restricts the drive letter support. */
# ifdef NO_CHDIR2
# warning NO_CHDIR2: usage of drive letters restricted
# undef chdir
# undef getcwd
# endif
#endif
#ifndef initialize_main
# define initialize_main(pargc, pargv)
#endif
/* Some systems (like Solaris, PTX, etc.) do not support the SA_RESTART flag /* Some systems (like Solaris, PTX, etc.) do not support the SA_RESTART flag
properly according to POSIX. So, we try to wrap common system calls with properly according to POSIX. So, we try to wrap common system calls with

12
read.c
View File

@ -561,12 +561,16 @@ eval (struct ebuffer *ebuf, int set_default)
} }
} }
/* This line is not a shell command line. Don't worry about tabs. */ /* This line is not a shell command line. Don't worry about tabs.
Get more space if we need it; we don't need to preserve the current
contents of the buffer. */
if (collapsed_length < linelen+1) if (collapsed_length < linelen+1)
{ {
collapsed_length = linelen+1; collapsed_length = linelen+1;
collapsed = (char *) xrealloc (collapsed, collapsed_length); if (collapsed)
free ((char *)collapsed);
collapsed = (char *) xmalloc (collapsed_length);
} }
strcpy (collapsed, line); strcpy (collapsed, line);
/* Collapse continuation lines. */ /* Collapse continuation lines. */
@ -1150,7 +1154,7 @@ eval (struct ebuffer *ebuf, int set_default)
do { do {
check_again = 0; check_again = 0;
/* For DOS paths, skip a "C:\..." or a "C:/..." */ /* For DOS-style paths, skip a "C:\..." or a "C:/..." */
if (p != 0 && (p[1] == '\\' || p[1] == '/') && if (p != 0 && (p[1] == '\\' || p[1] == '/') &&
isalpha ((unsigned char)p[-1]) && isalpha ((unsigned char)p[-1]) &&
(p == p2 + 1 || strchr (" \t:(", p[-2]) != 0)) { (p == p2 + 1 || strchr (" \t:(", p[-2]) != 0)) {
@ -2559,7 +2563,7 @@ readline (struct ebuffer *ebuf)
/* We got a newline, so add one to the count of lines. */ /* We got a newline, so add one to the count of lines. */
++nlines; ++nlines;
#if !defined(WINDOWS32) && !defined(__MSDOS__) #if !defined(WINDOWS32) && !defined(__MSDOS__) && !defined(__EMX__)
/* Check to see if the line was really ended with CRLF; if so ignore /* Check to see if the line was really ended with CRLF; if so ignore
the CR. */ the CR. */
if ((p - start) > 1 && p[-2] == '\r') if ((p - start) > 1 && p[-2] == '\r')

View File

@ -1200,6 +1200,14 @@ f_mtime (struct file *file, int search)
FILE_TIMESTAMP adjustment = FAT_ADJ_OFFSET << FILE_TIMESTAMP_LO_BITS; FILE_TIMESTAMP adjustment = FAT_ADJ_OFFSET << FILE_TIMESTAMP_LO_BITS;
if (ORDINARY_MTIME_MIN + adjustment <= adjusted_mtime) if (ORDINARY_MTIME_MIN + adjustment <= adjusted_mtime)
adjusted_mtime -= adjustment; adjusted_mtime -= adjustment;
#elif defined(__EMX__)
/* FAT filesystems round time to the nearest even second!
Allow for any file (NTFS or FAT) to perhaps suffer from this
brain damage. */
FILE_TIMESTAMP adjustment = (((FILE_TIMESTAMP_S (adjusted_mtime) & 1) == 0
&& FILE_TIMESTAMP_NS (adjusted_mtime) == 0)
? (FILE_TIMESTAMP) 1 << FILE_TIMESTAMP_LO_BITS
: 0);
#endif #endif
/* If the file's time appears to be in the future, update our /* If the file's time appears to be in the future, update our

View File

@ -544,7 +544,7 @@ merge_variable_set_lists (struct variable_set_list **setlist0,
void void
define_automatic_variables (void) define_automatic_variables (void)
{ {
#ifdef WINDOWS32 #if defined(WINDOWS32) || defined(__EMX__)
extern char* default_shell; extern char* default_shell;
#else #else
extern char default_shell[]; extern char default_shell[];
@ -585,6 +585,54 @@ define_automatic_variables (void)
(void) define_variable (shell_str, shlen, comp->value, o_env, 0); (void) define_variable (shell_str, shlen, comp->value, o_env, 0);
} }
} }
#elif defined(__EMX__)
{
static char shell_str[] = "SHELL";
const int shlen = sizeof (shell_str) - 1;
struct variable *shell = lookup_variable (shell_str, shlen);
struct variable *replace = lookup_variable ("MAKESHELL", 9);
/* if $MAKESHELL is defined in the environment assume o_env_override */
if (replace && *replace->value && replace->origin == o_env)
replace->origin = o_env_override;
/* if $MAKESHELL is not defined use $SHELL but only if the variable
did not come from the environment */
if (!replace || !*replace->value)
if (shell && *shell->value && (shell->origin == o_env
|| shell->origin == o_env_override))
{
/* overwrite whatever we got from the environment */
free(shell->value);
shell->value = xstrdup (default_shell);
shell->origin = o_default;
}
/* Some people do not like cmd to be used as the default
if $SHELL is not defined in the Makefile.
With -DNO_CMD_DEFAULT you can turn off this behaviour */
# ifndef NO_CMD_DEFAULT
/* otherwise use $COMSPEC */
if (!replace || !*replace->value)
replace = lookup_variable ("COMSPEC", 7);
/* otherwise use $OS2_SHELL */
if (!replace || !*replace->value)
replace = lookup_variable ("OS2_SHELL", 9);
# else
# warning NO_CMD_DEFAULT: GNU make will not use CMD.EXE as default shell
# endif
if (replace && *replace->value)
/* overwrite $SHELL */
(void) define_variable (shell_str, shlen, replace->value,
replace->origin, 0);
else
/* provide a definition if there is none */
(void) define_variable (shell_str, shlen, default_shell,
o_default, 0);
}
#endif #endif
/* This won't override any definition, but it /* This won't override any definition, but it
@ -594,8 +642,10 @@ define_automatic_variables (void)
/* On MSDOS we do use SHELL from environment, since /* On MSDOS we do use SHELL from environment, since
it isn't a standard environment variable on MSDOS, it isn't a standard environment variable on MSDOS,
so whoever sets it, does that on purpose. */ so whoever sets it, does that on purpose.
#ifndef __MSDOS__ On OS/2 we do not use SHELL from environment but
we have already handled that problem above. */
#if !defined(__MSDOS__) && !defined(__EMX__)
/* Don't let SHELL come from the environment. */ /* Don't let SHELL come from the environment. */
if (*v->value == '\0' || v->origin == o_env || v->origin == o_env_override) if (*v->value == '\0' || v->origin == o_env || v->origin == o_env_override)
{ {

View File

@ -247,7 +247,7 @@ construct_vpath_list (char *pattern, char *dirpath)
len = p - v; len = p - v;
/* Make sure there's no trailing slash, /* Make sure there's no trailing slash,
but still allow "/" as a directory. */ but still allow "/" as a directory. */
#ifdef __MSDOS__ #if defined(__MSDOS__) || defined(__EMX__)
/* We need also to leave alone a trailing slash in "d:/". */ /* We need also to leave alone a trailing slash in "d:/". */
if (len > 3 || (len > 1 && v[1] != ':')) if (len > 3 || (len > 1 && v[1] != ':'))
#endif #endif