[handle_excessive_command_length]: Patch to fix large cmmand line

When presented with a very very long command line (e.g. WebKit's linking
of libWebCore.la in current git), make fails to execute the command as
it doesn't split the command line to fit within the limits.

This patch provides a POSIX specific fix.

Signed-off-by: Manoj Srivastava <srivasta@golden-gryphon.com>
This commit is contained in:
Manoj Srivastava 2014-05-04 17:08:48 -07:00
parent b5ba68e8f0
commit 407e2fb313
2 changed files with 52 additions and 2 deletions

View file

@ -62,7 +62,8 @@ AC_HEADER_DIRENT
AC_HEADER_STAT
AC_HEADER_TIME
AC_CHECK_HEADERS([stdlib.h locale.h unistd.h limits.h fcntl.h string.h \
memory.h sys/param.h sys/resource.h sys/time.h sys/timeb.h])
memory.h sys/param.h sys/resource.h sys/time.h sys/timeb.h \
sys/user.h linux/binfmts.h])
AM_PROG_CC_C_O
AC_C_CONST

51
job.c
View file

@ -27,6 +27,14 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
#include <string.h>
#if defined (HAVE_LINUX_BINFMTS_H) && defined (HAVE_SYS_USER_H)
#include <sys/user.h>
#include <linux/binfmts.h>
#endif
#ifndef PAGE_SIZE
# define PAGE_SIZE (sysconf(_SC_PAGESIZE))
#endif
/* Default shell to use. */
#ifdef WINDOWS32
#include <windows.h>
@ -3057,6 +3065,7 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
#ifdef WINDOWS32
char *command_ptr = NULL; /* used for batch_mode_shell mode */
#endif
char *args_ptr;
# ifdef __EMX__ /* is this necessary? */
if (!unixy_shell && shellflags)
@ -3222,8 +3231,17 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
return new_argv;
}
#ifdef MAX_ARG_STRLEN
static char eval_line[] = "eval\\ \\\"set\\ x\\;\\ shift\\;\\ ";
#define ARG_NUMBER_DIGITS 5
#define EVAL_LEN (sizeof(eval_line)-1 + shell_len + 4 \
+ (7 + ARG_NUMBER_DIGITS) * 2 * line_len / (MAX_ARG_STRLEN - 2))
#else
#define EVAL_LEN 0
#endif
new_line = xmalloc ((shell_len*2) + 1 + sflags_len + 1
+ (line_len*2) + 1);
+ (line_len*2) + 1 + EVAL_LEN);
ap = new_line;
/* Copy SHELL, escaping any characters special to the shell. If
we don't escape them, construct_command_argv_internal will
@ -3243,6 +3261,30 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
#ifdef WINDOWS32
command_ptr = ap;
#endif
#if !defined (WINDOWS32) && defined (MAX_ARG_STRLEN)
if (unixy_shell && line_len > MAX_ARG_STRLEN)
{
unsigned j;
memcpy (ap, eval_line, sizeof (eval_line) - 1);
ap += sizeof (eval_line) - 1;
for (j = 1; j <= 2 * line_len / (MAX_ARG_STRLEN - 2); j++)
ap += sprintf (ap, "\\$\\{%u\\}", j);
*ap++ = '\\';
*ap++ = '"';
*ap++ = ' ';
/* Copy only the first word of SHELL to $0. */
for (p = shell; *p != '\0'; ++p)
{
if (isspace ((unsigned char)*p))
break;
*ap++ = *p;
}
*ap++ = ' ';
}
#endif
args_ptr = ap;
for (p = line; *p != '\0'; ++p)
{
if (restp != NULL && *p == '\n')
@ -3290,6 +3332,13 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
}
#endif
*ap++ = *p;
#if !defined (WINDOWS32) && defined (MAX_ARG_STRLEN)
if (unixy_shell && line_len > MAX_ARG_STRLEN && (ap - args_ptr > MAX_ARG_STRLEN - 2))
{
*ap++ = ' ';
args_ptr = ap;
}
#endif
}
if (ap == new_line + shell_len + sflags_len + 2)
{