/* * This routine is a replacement for the old, horrible strcat() loop * that was used to turn the argv[] array into a string for CreateProcess(). * It's about a zillion times faster. * -amol 2/4/99 */ char *concat_args_and_quote(char **args, char **poriginalPtr,char **cstr, unsigned int *clen, char **cend, unsigned int *cmdsize) { unsigned int argcount, arglen, cmdlen; char *tempptr, *cmdend ,*cmdstr; short quotespace = 0; short quotequote = 0; short noquoteprotect = 0; char *tempquotedbuf; unsigned long tqlen = 256; int rc; dprintf("entering concat_args_and_quote\n"); tempquotedbuf = heap_alloc(tqlen); noquoteprotect = (varval(STRNTnoquoteprotect) != STRNULL); /* quotespace hack needed since execv() would have separated args, but createproces doesnt -amol 9/14/96 */ cmdend= *cend; cmdstr = *cstr; cmdlen = *clen; argcount = 0; while (*args) { *cmdend++ = ' '; cmdlen++; tempptr = *args; arglen = 0; argcount++; //dprintf("args is %s\n",*args); if (!*tempptr) { *cmdend++ = '"'; *cmdend++ = '"'; } while(*tempptr) { if (*tempptr == ' ' || *tempptr == '\t') quotespace = 1; else if (*tempptr == '"') quotequote = 1; tempptr++; arglen++; } if (arglen + cmdlen +4 > *cmdsize) { // +4 is if we have to quote dprintf("before realloc: original %p, cmdstr %p\n", *poriginalPtr,cmdstr); tempptr = heap_realloc(*poriginalPtr,*cmdsize<<1); if(!tempptr) return NULL; // If it's not the same heap block, re-adjust the pointers. if (tempptr != *poriginalPtr) { cmdstr = tempptr + (cmdstr - *poriginalPtr); cmdend = tempptr + (cmdend- *poriginalPtr); *poriginalPtr = tempptr; } dprintf("after realloc: original %p, cmdstr %p\n", *poriginalPtr,cmdstr); *cmdsize <<=1; } if (quotespace) *cmdend++ = '"'; if ((noquoteprotect == 0) && quotequote){ tempquotedbuf[0]=0; tempptr = &tempquotedbuf[0]; rc = quoteProtect(tempquotedbuf,*args,tqlen); while(rc == ERROR_BUFFER_OVERFLOW) { tempquotedbuf = heap_realloc(tempquotedbuf,tqlen <<1); tqlen <<= 1; tempptr = &tempquotedbuf[0]; rc = quoteProtect(tempquotedbuf,*args,tqlen); } while (*tempptr) { *cmdend = *tempptr; cmdend++; tempptr++; } cmdlen +=2; } else { tempptr = *args; while(*tempptr) { *cmdend = *tempptr; cmdend++; tempptr++; } } if (quotespace) { *cmdend++ = '"'; cmdlen +=2; } cmdlen += arglen; args++; } *clen = cmdlen; *cend = cmdend; *cstr = cmdstr; heap_free(tempquotedbuf); return cmdstr; }
/* * args is the const array to be quoted and concatenated * *cstr is the resulting string * *clen is current cstr size * *cend points to the end of the constructed string * *cmdsize is the cstr buffer size * * PROBLEMS: * - heap_realloc() is not tested for failure * - when re-allocating the passed-in *cstr pointer is lost, generating a leak * * This routine is a replacement for the old, horrible strcat() loop * that was used to turn the argv[] array into a string for CreateProcess(). * It's about a zillion times faster. * -amol 2/4/99 */ static void concat_args_and_quote(const char *const *args, char **cstr, size_t *clen, char **cend, unsigned int *cmdsize) { unsigned int argcount, arglen; size_t cmdlen; const char *tempptr; char *cmdend, *cmdstr; short quotespace; short quotequote; short n_quotequote; /* quotespace hack needed since execv() would have separated args, but createproces doesnt -amol 9/14/96 */ cmdend= *cend; cmdstr = *cstr; cmdlen = *clen; argcount = 0; while (*args && (cmdlen < 65500) ) { argcount++; arglen = 0; /* first, count the current argument and check if we need to quote. */ quotespace = quotequote = n_quotequote = 0; tempptr = *args; if(!*tempptr) { /* check for empty argument, will be replaced by "" */ quotespace = 1; } else { /* count spaces, tabs and quotes. */ while(*tempptr) { if (*tempptr == ' ' || *tempptr == '\t') quotespace = 1; else if (*tempptr == '"') { quotequote = 1; n_quotequote++; } else if (*tempptr == '\\') { n_quotequote++; } tempptr++; arglen++; } } /* Next, realloc target string if necessary */ while (cmdlen + 2 + arglen + 2*quotespace + quotequote * n_quotequote > *cmdsize) { tempptr = cmdstr; dbgprintf(PR_WARN, "Heap realloc before %p\n", cmdstr); cmdstr = (char *)heap_realloc(cmdstr, *cmdsize<<1); /* @@@@ does NOT test for failure ... */ if (tempptr != cmdstr) { cmdend = cmdstr + (cmdend-tempptr); } dbgprintf(PR_WARN, "Heap realloc after %p\n", cmdstr); *cmdsize <<=1; } /* add space before next argument */ *cmdend++ = ' '; cmdlen++; if (quotespace) { /* we need to quote, so output a quote. */ *cmdend++ = '"'; cmdlen++; } if (n_quotequote > 0){ /* quote quotes and copy into the destination */ *cmdend=0; quoteProtect(cmdend,*args); while(*cmdend) { cmdend++; cmdlen++; } } else { /* directly copy the argument into the destination */ tempptr = *args; while(*tempptr) { *cmdend++ = *tempptr++; cmdlen++; } } if (quotespace) { *cmdend++ = '"'; cmdlen ++; } args++; } *clen = cmdlen; *cend = cmdend; *cstr = cmdstr; }