* Run a shell command. The result is assigned to the variable if not NULL. * Return true if succeeded, or false on error. */
| 2736 | * Return true if succeeded, or false on error. |
| 2737 | */ |
| 2738 | static bool |
| 2739 | runShellCommand(CState *st, char *variable, char **argv, int argc) |
| 2740 | { |
| 2741 | char command[SHELL_COMMAND_SIZE]; |
| 2742 | int i, |
| 2743 | len = 0; |
| 2744 | FILE *fp; |
| 2745 | char res[64]; |
| 2746 | char *endptr; |
| 2747 | int retval; |
| 2748 | |
| 2749 | /*---------- |
| 2750 | * Join arguments with whitespace separators. Arguments starting with |
| 2751 | * exactly one colon are treated as variables: |
| 2752 | * name - append a string "name" |
| 2753 | * :var - append a variable named 'var' |
| 2754 | * ::name - append a string ":name" |
| 2755 | *---------- |
| 2756 | */ |
| 2757 | for (i = 0; i < argc; i++) |
| 2758 | { |
| 2759 | char *arg; |
| 2760 | int arglen; |
| 2761 | |
| 2762 | if (argv[i][0] != ':') |
| 2763 | { |
| 2764 | arg = argv[i]; /* a string literal */ |
| 2765 | } |
| 2766 | else if (argv[i][1] == ':') |
| 2767 | { |
| 2768 | arg = argv[i] + 1; /* a string literal starting with colons */ |
| 2769 | } |
| 2770 | else if ((arg = getVariable(st, argv[i] + 1)) == NULL) |
| 2771 | { |
| 2772 | pg_log_error("%s: undefined variable \"%s\"", argv[0], argv[i]); |
| 2773 | return false; |
| 2774 | } |
| 2775 | |
| 2776 | arglen = strlen(arg); |
| 2777 | if (len + arglen + (i > 0 ? 1 : 0) >= SHELL_COMMAND_SIZE - 1) |
| 2778 | { |
| 2779 | pg_log_error("%s: shell command is too long", argv[0]); |
| 2780 | return false; |
| 2781 | } |
| 2782 | |
| 2783 | if (i > 0) |
| 2784 | command[len++] = ' '; |
| 2785 | memcpy(command + len, arg, arglen); |
| 2786 | len += arglen; |
| 2787 | } |
| 2788 | |
| 2789 | command[len] = '\0'; |
| 2790 | |
| 2791 | /* Fast path for non-assignment case */ |
| 2792 | if (variable == NULL) |
| 2793 | { |
| 2794 | if (system(command)) |
| 2795 | { |
no test coverage detected