Module Name: src Committed By: sjg Date: Thu Jul 11 20:09:16 UTC 2024
Modified Files: src/usr.bin/make: compat.c main.c make.h src/usr.bin/make/unit-tests: var-op-shell.mk Log Message: Compat_RunCommand use tempfile if cmd too big Extract the logic recently added to Cmd_Exec to handle long commands via temp file to Cmd_Argv, so it can also be leveraged by Compat_RunCommand Reviewed by: christos To generate a diff of this commit: cvs rdiff -u -r1.259 -r1.260 src/usr.bin/make/compat.c cvs rdiff -u -r1.631 -r1.632 src/usr.bin/make/main.c cvs rdiff -u -r1.343 -r1.344 src/usr.bin/make/make.h cvs rdiff -u -r1.9 -r1.10 src/usr.bin/make/unit-tests/var-op-shell.mk Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/make/compat.c diff -u src/usr.bin/make/compat.c:1.259 src/usr.bin/make/compat.c:1.260 --- src/usr.bin/make/compat.c:1.259 Sat Jun 15 20:02:45 2024 +++ src/usr.bin/make/compat.c Thu Jul 11 20:09:16 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: compat.c,v 1.259 2024/06/15 20:02:45 rillig Exp $ */ +/* $NetBSD: compat.c,v 1.260 2024/07/11 20:09:16 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -91,7 +91,7 @@ #include "pathnames.h" /* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: compat.c,v 1.259 2024/06/15 20:02:45 rillig Exp $"); +MAKE_RCSID("$NetBSD: compat.c,v 1.260 2024/07/11 20:09:16 sjg Exp $"); static GNode *curTarg = NULL; static pid_t compatChild; @@ -246,6 +246,8 @@ Compat_RunCommand(const char *cmdp, GNod bool useShell; /* True if command should be executed using a * shell */ const char *cmd = cmdp; + char cmd_file[MAXPATHLEN]; + size_t cmd_len; silent = (gn->type & OP_SILENT) != OP_NONE; errCheck = !(gn->type & OP_IGNORE); @@ -316,20 +318,20 @@ Compat_RunCommand(const char *cmdp, GNod DEBUG1(JOB, "Execute: '%s'\n", cmd); - if (useShell && shellPath == NULL) - Shell_Init(); /* we need shellPath */ + cmd_len = strlen(cmd); + if (cmd_len > MAKE_CMDLEN_LIMIT) + useShell = true; + else + cmd_file[0] = '\0'; if (useShell) { static const char *shargv[5]; - /* The following work for any of the builtin shell specs. */ - int shargc = 0; - shargv[shargc++] = shellPath; - if (errCheck && shellErrFlag != NULL) - shargv[shargc++] = shellErrFlag; - shargv[shargc++] = DEBUG(SHELL) ? "-xc" : "-c"; - shargv[shargc++] = cmd; - shargv[shargc] = NULL; + if (Cmd_Argv(cmd, cmd_len, shargv, 5, + cmd_file, sizeof(cmd_file), + (errCheck && shellErrFlag != NULL), + DEBUG(SHELL)) < 0) + Fatal("cannot run \"%s\"", cmd); av = shargv; bp = NULL; mav = NULL; @@ -422,6 +424,8 @@ Compat_RunCommand(const char *cmdp, GNod } free(cmdStart); + if (cmd_file[0] != '\0') + unlink(cmd_file); compatChild = 0; if (compatSigno != 0) { bmake_signal(compatSigno, SIG_DFL); Index: src/usr.bin/make/main.c diff -u src/usr.bin/make/main.c:1.631 src/usr.bin/make/main.c:1.632 --- src/usr.bin/make/main.c:1.631 Tue Jul 9 19:43:01 2024 +++ src/usr.bin/make/main.c Thu Jul 11 20:09:16 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.631 2024/07/09 19:43:01 rillig Exp $ */ +/* $NetBSD: main.c,v 1.632 2024/07/11 20:09:16 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -111,7 +111,7 @@ #include "trace.h" /* "@(#)main.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: main.c,v 1.631 2024/07/09 19:43:01 rillig Exp $"); +MAKE_RCSID("$NetBSD: main.c,v 1.632 2024/07/11 20:09:16 sjg Exp $"); #if defined(MAKE_NATIVE) __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 " "The Regents of the University of California. " @@ -1685,6 +1685,56 @@ found: return true; } +/* populate av for Cmd_Exec and Compat_RunCommand */ +int +Cmd_Argv(const char *cmd, size_t cmd_len, const char **av, size_t avsz, + char *cmd_file, size_t cmd_filesz, bool eflag, bool xflag) +{ + int ac = 0; + int cmd_fd = -1; + + if (shellPath == NULL) + Shell_Init(); + + if (cmd_file != NULL) { + if (cmd_len == 0) + cmd_len = strlen(cmd); + + if (cmd_len > MAKE_CMDLEN_LIMIT) { + cmd_fd = mkTempFile(NULL, cmd_file, cmd_filesz); + if (cmd_fd >= 0) { + ssize_t n; + + n = write(cmd_fd, cmd, cmd_len); + close(cmd_fd); + if (n < (ssize_t)cmd_len) { + unlink(cmd_file); + cmd_fd = -1; + } + } + } else + cmd_file[0] = '\0'; + } + + if (avsz < 4 || (eflag && avsz < 5)) + return -1; + + /* The following works for any of the builtin shell specs. */ + av[ac++] = shellPath; + if (eflag) + av[ac++] = shellErrFlag; + if (cmd_fd >= 0) { + if (xflag) + av[ac++] = "-x"; + av[ac++] = cmd_file; + } else { + av[ac++] = xflag ? "-xc" : "-c"; + av[ac++] = cmd; + } + av[ac] = NULL; + return ac; +} + /* * Execute the command in cmd, and return its output (only stdout, not * stderr, possibly empty). In the output, replace newlines with spaces. @@ -1703,40 +1753,11 @@ Cmd_Exec(const char *cmd, char **error) char *p; int saved_errno; char cmd_file[MAXPATHLEN]; - size_t cmd_len; - int cmd_fd = -1; - - if (shellPath == NULL) - Shell_Init(); - cmd_len = strlen(cmd); - if (cmd_len > 1000) { - cmd_fd = mkTempFile(NULL, cmd_file, sizeof(cmd_file)); - if (cmd_fd >= 0) { - ssize_t n; - - n = write(cmd_fd, cmd, cmd_len); - close(cmd_fd); - if (n < (ssize_t)cmd_len) { - unlink(cmd_file); - cmd_fd = -1; - } - } - } - - args[0] = shellName; - if (cmd_fd >= 0) { - args[1] = cmd_file; - args[2] = NULL; - } else { - cmd_file[0] = '\0'; - args[1] = "-c"; - args[2] = cmd; - args[3] = NULL; - } DEBUG1(VAR, "Capturing the output of command \"%s\"\n", cmd); - if (pipe(pipefds) == -1) { + if (Cmd_Argv(cmd, 0, args, 4, cmd_file, sizeof(cmd_file), false, false) < 0 + || pipe(pipefds) == -1) { *error = str_concat3( "Couldn't create pipe for \"", cmd, "\""); return bmake_strdup(""); Index: src/usr.bin/make/make.h diff -u src/usr.bin/make/make.h:1.343 src/usr.bin/make/make.h:1.344 --- src/usr.bin/make/make.h:1.343 Tue Jul 9 19:43:01 2024 +++ src/usr.bin/make/make.h Thu Jul 11 20:09:16 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: make.h,v 1.343 2024/07/09 19:43:01 rillig Exp $ */ +/* $NetBSD: make.h,v 1.344 2024/07/11 20:09:16 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -845,8 +845,13 @@ void For_Break(struct ForLoop *); /* job.c */ void JobReapChild(pid_t, int, bool); +/* longer than this we use a temp file */ +#ifndef MAKE_CMDLEN_LIMIT +# define MAKE_CMDLEN_LIMIT 1000 +#endif /* main.c */ void Main_ParseArgLine(const char *); +int Cmd_Argv(const char *, size_t, const char **, size_t, char *, size_t, bool, bool); char *Cmd_Exec(const char *, char **) MAKE_ATTR_USE; void Error(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2); void Fatal(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2) MAKE_ATTR_DEAD; Index: src/usr.bin/make/unit-tests/var-op-shell.mk diff -u src/usr.bin/make/unit-tests/var-op-shell.mk:1.9 src/usr.bin/make/unit-tests/var-op-shell.mk:1.10 --- src/usr.bin/make/unit-tests/var-op-shell.mk:1.9 Sun Jun 30 11:37:21 2024 +++ src/usr.bin/make/unit-tests/var-op-shell.mk Thu Jul 11 20:09:16 2024 @@ -1,4 +1,4 @@ -# $NetBSD: var-op-shell.mk,v 1.9 2024/06/30 11:37:21 rillig Exp $ +# $NetBSD: var-op-shell.mk,v 1.10 2024/07/11 20:09:16 sjg Exp $ # # Tests for the != variable assignment operator, which runs its right-hand # side through the shell. @@ -99,7 +99,7 @@ OUTPUT_SHORT!= echo "$$0" OUTPUT_LONG!= echo "$$0" || : ${:U:range=1000} # When running '$shell -c $command', '$0' in the shell evaluates to the name # of the shell. -.if ${OUTPUT_SHORT} != ${.SHELL:T} +.if ${OUTPUT_SHORT:T} != ${.SHELL:T} . error .endif # When running '$shell $tmpfile', '$0' in the shell evaluates to the name of