diff --git a/configure.ac b/configure.ac index 96847494..75006cf7 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/job.c b/job.c index febfac0c..01971615 100644 --- a/job.c +++ b/job.c @@ -27,6 +27,14 @@ this program. If not, see . */ #include +#if defined (HAVE_LINUX_BINFMTS_H) && defined (HAVE_SYS_USER_H) +#include +#include +#endif +#ifndef PAGE_SIZE +# define PAGE_SIZE (sysconf(_SC_PAGESIZE)) +#endif + /* Default shell to use. */ #ifdef WINDOWS32 #include @@ -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) {