1diff --git a/backend/beh.c b/backend/beh.c 2index 225fd27d..80f51b06 100644 3--- a/backend/beh.c 4+++ b/backend/beh.c 5@@ -22,12 +22,12 @@ 6 #include "backend-private.h" 7 #include <cups/array.h> 8 #include <ctype.h> 9- 10+#include <sys/wait.h> 11 /* 12 * Local globals... 13 */ 14 15-static int job_canceled = 0; /* Set to 1 on SIGTERM */ 16+static volatile int job_canceled = 0; /* Set to 1 on SIGTERM */ 17 18 /* 19 * Local functions... 20@@ -213,21 +213,44 @@ call_backend(char *uri, /* I - URI of final destination */ 21 char **argv, /* I - Command-line arguments */ 22 char *filename) { /* I - File name of input data */ 23 const char *cups_serverbin; /* Location of programs */ 24+ char *backend_argv[8]; // Arguments for called CUPS backend 25 char scheme[1024], /* Scheme from URI */ 26 *ptr, /* Pointer into scheme */ 27- cmdline[65536]; /* Backend command line */ 28- int retval; 29+ backend_path[2048]; // Backend path 30+ int pid, 31+ wait_pid, 32+ wait_status, 33+ retval = 0, 34+ int bytes; 35 36 /* 37 * Build the backend command line... 38 */ 39 40- strncpy(scheme, uri, sizeof(scheme) - 1); 41- if (strlen(uri) > 1023) 42- scheme[1023] = '\0'; 43+ scheme[0] = '\0'; 44+ strncat(scheme, uri, sizeof(scheme) - 1); 45+ 46 if ((ptr = strchr(scheme, ':')) != NULL) 47 *ptr = '\0'; 48- 49+ else 50+ { 51+ fprintf(stderr, 52+ "ERROR: beh: Invalid URI, no colon (':') to mark end of scheme part.\n"); 53+ exit (CUPS_BACKEND_FAILED); 54+ } 55+ if (strchr(scheme, '/')) 56+ { 57+ fprintf(stderr, 58+ "ERROR: beh: Invalid URI, scheme contains a slash ('/').\n"); 59+ exit (CUPS_BACKEND_FAILED); 60+ } 61+ if (!strcmp(scheme, ".") || !strcmp(scheme, "..")) 62+ { 63+ fprintf(stderr, 64+ "ERROR: beh: Invalid URI, scheme (\"%s\") is a directory.\n", 65+ scheme); 66+ exit (CUPS_BACKEND_FAILED); 67+ } 68 if ((cups_serverbin = getenv("CUPS_SERVERBIN")) == NULL) 69 cups_serverbin = CUPS_SERVERBIN; 70 71@@ -235,17 +258,28 @@ call_backend(char *uri, /* I - URI of final destination */ 72 fprintf(stderr, 73 "ERROR: beh: Direct output into a file not supported.\n"); 74 exit (CUPS_BACKEND_FAILED); 75- } else 76- snprintf(cmdline, sizeof(cmdline), 77- "%s/backend/%s '%s' '%s' '%s' '%s' '%s' %s", 78- cups_serverbin, scheme, argv[1], argv[2], argv[3], 79- /* Apply number of copies only if beh was called with a 80- file name and not with the print data in stdin, as 81- backends should handle copies only if they are called 82- with a file name */ 83- (argc == 6 ? "1" : argv[4]), 84- argv[5], filename); 85- 86+ } 87+ 88+ backend_argv[0] = uri; 89+ backend_argv[1] = argv[1]; 90+ backend_argv[2] = argv[2]; 91+ backend_argv[3] = argv[3]; 92+ backend_argv[4] = (argc == 6 ? "1" : argv[4]); 93+ backend_argv[5] = argv[5]; 94+ backend_argv[6] = filename; 95+ backend_argv[7] = NULL; 96+ 97+ bytes = snprintf(backend_path, sizeof(backend_path), 98+ "%s/backend/%s", cups_serverbin, scheme); 99+ if (bytes < 0 || bytes >= sizeof(backend_path)) 100+ { 101+ fprintf(stderr, 102+ "ERROR: beh: Invalid scheme (\"%s\"), could not determing backend path.\n", 103+ scheme); 104+ exit (CUPS_BACKEND_FAILED); 105+ } 106+ 107+ 108 /* 109 * Overwrite the device URI and run the actual backend... 110 */ 111@@ -253,17 +287,42 @@ call_backend(char *uri, /* I - URI of final destination */ 112 setenv("DEVICE_URI", uri, 1); 113 114 fprintf(stderr, 115- "DEBUG: beh: Executing backend command line \"%s\"...\n", 116- cmdline); 117+ "DEBUG: beh: Executing backend command line \"%s '%s' '%s' '%s' '%s' '%s'%s%s\"...\n", 118+ backend_path, backend_argv[1], backend_argv[2], backend_argv[3], 119+ backend_argv[4], backend_argv[5], 120+ (backend_argv[6] && backend_argv[6][0] ? " " : ""), 121+ (backend_argv[6] && backend_argv[6][0] ? backend_argv[6] : "")); 122 fprintf(stderr, 123 "DEBUG: beh: Using device URI: %s\n", 124 uri); 125 126- retval = system(cmdline) >> 8; 127+ if ((pid = fork()) == 0) 128+ { 129+ retval = execv(backend_path, backend_argv); 130 131- if (retval == -1) 132- fprintf(stderr, "ERROR: Unable to execute backend command line: %s\n", 133- strerror(errno)); 134+ if (retval == -1) 135+ fprintf(stderr, "ERROR: Unable to execute backend: %s\n", 136+ strerror(errno)); 137+ exit (CUPS_BACKEND_FAILED); 138+ } 139+ else if (pid < 0) 140+ { 141+ fprintf(stderr, "ERROR: Unable to fork for backend\n"); 142+ return (CUPS_BACKEND_FAILED); 143+ } 144+ 145+ while ((wait_pid = wait(&wait_status)) < 0 && errno == EINTR); 146+ 147+ if (wait_pid >= 0 && wait_status) 148+ { 149+ if (WIFEXITED(wait_status)) 150+ retval = WEXITSTATUS(wait_status); 151+ else if (WTERMSIG(wait_status) != SIGTERM) 152+ retval = WTERMSIG(wait_status); 153+ else 154+ retval = 0; 155+ } 156+ 157 158 return (retval); 159 } 160@@ -277,8 +336,10 @@ static void 161 sigterm_handler(int sig) { /* I - Signal number (unused) */ 162 (void)sig; 163 164- fprintf(stderr, 165- "DEBUG: beh: Job canceled.\n"); 166+ const char * const msg = "DEBUG: beh: Job canceled.\n"; 167+ // The if() is to eliminate the return value and silence the warning 168+ // about an unused return value. 169+ if (write(2, msg, strlen(msg))); 170 171 if (job_canceled) 172 _exit(CUPS_BACKEND_OK); 173