| 11 |  | #include <stdlib.h> | 
| 12 |  | #include "rtio.h" | 
| 13 |  | #include "rtmath.h" | 
| 14 | < | #include "rtprocess.h" | 
| 14 | > | #include "paths.h" | 
| 15 |  | #include "bsdf.h" | 
| 16 |  | #include "bsdf_m.h" | 
| 17 |  | #include "random.h" | 
| 23 |  | #define getc    getc_unlocked | 
| 24 |  | #endif | 
| 25 |  |  | 
| 26 | – | #ifdef _WIN32 | 
| 27 | – | #define SPECIALS        " \t\"$*?" | 
| 28 | – | #define QUOTCHAR        '"' | 
| 29 | – | #else | 
| 30 | – | #define SPECIALS        " \t\n'\"()${}*?[];|&" | 
| 31 | – | #define QUOTCHAR        '\'' | 
| 32 | – | #define ALTQUOT         '"' | 
| 33 | – | #endif | 
| 34 | – |  | 
| 26 |  | #define MAXRCARG        512 | 
| 27 |  |  | 
| 28 |  | char            *progname;              /* global argv[0] */ | 
| 147 |  | strcpy(cp, *av++); | 
| 148 |  | while (*cp) cp++; | 
| 149 |  | *cp++ = ' '; | 
| 150 | < | if (cp >= oconvbuf+(sizeof(oconvbuf)-32)) { | 
| 151 | < | fputs(progname, stderr); | 
| 161 | < | fputs(": too many file arguments!\n", stderr); | 
| 162 | < | exit(1); | 
| 163 | < | } | 
| 150 | > | if (cp >= oconvbuf+(sizeof(oconvbuf)-32)) | 
| 151 | > | goto overrun; | 
| 152 |  | } | 
| 153 | < | strcpy(cp, recv);       /* receiver goes last */ | 
| 153 | > | /* receiver goes last */ | 
| 154 | > | if (matchany(recv, SPECIALS)) { | 
| 155 | > | *cp++ = QUOTCHAR; | 
| 156 | > | while (*recv) { | 
| 157 | > | if (cp >= oconvbuf+(sizeof(oconvbuf)-3)) | 
| 158 | > | goto overrun; | 
| 159 | > | *cp++ = *recv++; | 
| 160 | > | } | 
| 161 | > | *cp++ = QUOTCHAR; | 
| 162 | > | *cp = '\0'; | 
| 163 | > | } else | 
| 164 | > | strcpy(cp, recv); | 
| 165 |  | return(oconvbuf); | 
| 166 | + | overrun: | 
| 167 | + | fputs(progname, stderr); | 
| 168 | + | fputs(": too many file arguments!\n", stderr); | 
| 169 | + | exit(1); | 
| 170 |  | } | 
| 171 |  |  | 
| 169 | – | /* Check if any of the characters in str2 are found in str1 */ | 
| 170 | – | static int | 
| 171 | – | matchany(const char *str1, const char *str2) | 
| 172 | – | { | 
| 173 | – | while (*str1) { | 
| 174 | – | const char      *cp = str2; | 
| 175 | – | while (*cp) | 
| 176 | – | if (*cp++ == *str1) | 
| 177 | – | return(*str1); | 
| 178 | – | ++str1; | 
| 179 | – | } | 
| 180 | – | return(0); | 
| 181 | – | } | 
| 182 | – |  | 
| 183 | – |  | 
| 184 | – | /* Convert a set of arguments into a command line for pipe() or system() */ | 
| 185 | – | static char * | 
| 186 | – | convert_commandline(char *cmd, const int len, char *av[]) | 
| 187 | – | { | 
| 188 | – | int     match; | 
| 189 | – | char    *cp; | 
| 190 | – |  | 
| 191 | – | for (cp = cmd; *av != NULL; av++) { | 
| 192 | – | const int       n = strlen(*av); | 
| 193 | – | if (cp+n >= cmd+(len-3)) { | 
| 194 | – | fputs(progname, stderr); | 
| 195 | – | return(NULL); | 
| 196 | – | } | 
| 197 | – | if ((match = matchany(*av, SPECIALS))) { | 
| 198 | – | const int       quote = | 
| 199 | – | #ifdef ALTQUOT | 
| 200 | – | (match == QUOTCHAR) ? ALTQUOT : | 
| 201 | – | #endif | 
| 202 | – | QUOTCHAR; | 
| 203 | – | *cp++ = quote; | 
| 204 | – | strcpy(cp, *av); | 
| 205 | – | cp += n; | 
| 206 | – | *cp++ = quote; | 
| 207 | – | } else { | 
| 208 | – | strcpy(cp, *av); | 
| 209 | – | cp += n; | 
| 210 | – | } | 
| 211 | – | *cp++ = ' '; | 
| 212 | – | } | 
| 213 | – | if (cp <= cmd) | 
| 214 | – | return(NULL); | 
| 215 | – | *--cp = '\0'; | 
| 216 | – | return(cmd); | 
| 217 | – | } | 
| 218 | – |  | 
| 172 |  | /* Open a pipe to/from a command given as an argument list */ | 
| 173 |  | static FILE * | 
| 174 |  | popen_arglist(char *av[], char *mode) | 
| 271 |  | { | 
| 272 |  | char    *cp = pargs; | 
| 273 |  | int     nparams = 0; | 
| 274 | + | int     quot; | 
| 275 |  | int     i; | 
| 276 |  |  | 
| 277 |  | for ( ; ; ) { | 
| 308 |  | case 'o': | 
| 309 |  | if (*cp++ != '=') | 
| 310 |  | break; | 
| 311 | + | quot = 0; | 
| 312 | + | if ((*cp == '"') | (*cp == '\'')) | 
| 313 | + | quot = *cp++; | 
| 314 |  | i = 0; | 
| 315 | < | while (*cp && !isspace(*cp++)) | 
| 316 | < | i++; | 
| 315 | > | while (*cp && (quot ? (*cp != quot) : !isspace(*cp))) { | 
| 316 | > | i++; cp++; | 
| 317 | > | } | 
| 318 |  | if (!i) | 
| 319 |  | break; | 
| 320 | < | *--cp = '\0'; | 
| 320 | > | if (!*cp) { | 
| 321 | > | if (quot) | 
| 322 | > | break; | 
| 323 | > | cp[1] = '\0'; | 
| 324 | > | } | 
| 325 | > | *cp = '\0'; | 
| 326 |  | p->outfn = savqstr(cp-i); | 
| 327 | < | *cp++ = ' '; | 
| 327 | > | *cp++ = quot ? quot : ' '; | 
| 328 |  | ++nparams; | 
| 329 |  | continue; | 
| 330 |  | case ' ': | 
| 493 |  | { | 
| 494 |  | int     i; | 
| 495 |  |  | 
| 496 | < | if (!getperpendicular(uva[0], nrm)) { | 
| 496 | > | if (!getperpendicular(uva[0], nrm, 1)) { | 
| 497 |  | fputs(progname, stderr); | 
| 498 |  | fputs(": bad surface normal in make_axes!\n", stderr); | 
| 499 |  | exit(1); | 
| 637 |  | /* special case for lone surface */ | 
| 638 |  | if (p->nsurfs == 1) { | 
| 639 |  | sp = p->slist; | 
| 640 | < | if (DOT(sp->snrm, rdir) >= -FTINY) { | 
| 640 | > | if (DOT(sp->snrm, rdir) >= FTINY) { | 
| 641 |  | fprintf(stderr, | 
| 642 |  | "%s: internal - sample behind sender '%s'\n", | 
| 643 |  | progname, sp->sname); |