http://bugs.gentoo.org/301116 tweaked a little to avoid regenerating autotools 2009-07-29 Ralf Wildenhues gmx.de> * configure.in: Check for sys/user.h and linux/binfmts.h headers. * job.c: Include them if available. (construct_command_argv_internal): When constructing the command line with 'sh -c', use multiple arguments together with eval expansion to evade the Linux per-argument length limit MAX_ARG_STRLEN if it is defined. Problem reported against Automake by Xan Lopez gnome.org>. --- job.c.orig 2010-01-15 18:36:53.000000000 +0200 +++ job.c 2010-01-15 18:41:09.000000000 +0200 @@ -29,6 +29,15 @@ #include +#if defined(__linux__) /* defined (HAVE_LINUX_BINFMTS_H) && defined (HAVE_SYS_USER_H) */ +#include +#include +#ifndef PAGE_SIZE +#define PAGE_SIZE sysconf(_SC_PAGE_SIZE) +#endif +#include +#endif + /* Default shell to use. */ #ifdef WINDOWS32 #include @@ -2697,9 +2702,19 @@ #endif unsigned int line_len = strlen (line); +#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 char *new_line = (char *) alloca (shell_len + (sizeof (minus_c) - 1) - + (line_len * 2) + 1); + + (line_len*2) + 1 + EVAL_LEN); + char *command_ptr = NULL; /* used for batch_mode_shell mode */ + char *args_ptr; # ifdef __EMX__ /* is this necessary? */ if (!unixy_shell) @@ -2712,6 +2727,30 @@ bcopy (minus_c, ap, sizeof (minus_c) - 1); ap += sizeof (minus_c) - 1; command_ptr = ap; + +#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') @@ -2760,6 +2799,14 @@ } #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 + sizeof (minus_c) - 1) /* Line was empty. */