ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/win_popen.c
(Generate patch)

Comparing ray/src/common/win_popen.c (file contents):
Revision 1.1 by schorsch, Tue Oct 21 19:20:37 2003 UTC vs.
Revision 1.5 by greg, Wed Oct 5 17:20:55 2011 UTC

# Line 29 | Line 29 | ignoring any | within. Quotes don't nest.
29  
30   #define RAD_MAX_PIPES 32 /* maximum number of pipes */
31  
32 < static int parse_pipes(char*, char**, int);
32 > #define R_MODE 1
33 > #define W_MODE 2
34 > #define A_MODE 3
35 >
36 > static int parse_pipes(char *s, char *lines[], char **infn, char **outfn,
37 > int *append, int maxl);
38   static BOOL createPipes(HANDLE*, HANDLE*, HANDLE*, HANDLE*);
39   static BOOL runChild(char*, char*, HANDLE, HANDLE, HANDLE);
40   static void resetStdHandles(HANDLE stdoutOrig, HANDLE stdinOrig);
41 + HANDLE newFile(char *fn, int mode);
42  
43  
44   int
45 < pclose(    /* posix pclose replacement */
45 > win_pclose(    /* posix pclose replacement */
46   FILE* p
47   )
48   {
# Line 47 | Line 53 | FILE* p
53  
54  
55   FILE *
56 < popen(     /* posix popen replacement */
56 > win_popen(     /* posix popen replacement */
57   char* command,
58   char* type
59   )
60   {
61          char *execfile, *args;
62          char *cmdlines[RAD_MAX_PIPES];
63 <        char executable[512];
64 <        int n, i;
63 >        char *infn = NULL, *outfn = NULL;
64 >        char executable[512], estr[512];
65 >        int n, i, mode = 0, append = 0;
66          int ncmds = 0;
67 +        FILE *inf = NULL;
68 +        char *s = NULL;
69          HANDLE stdoutRd = NULL, stdoutWr = NULL;
70          HANDLE stdinRd = NULL, stdinWr = NULL;
71          HANDLE stderrWr = NULL;
72          HANDLE stdoutOrig, stdinOrig;
73  
74 +        if (strchr(type, 'w')) {
75 +                mode = W_MODE;
76 +        } else if (strchr(type, 'r')) {
77 +                mode = R_MODE;
78 +        } else {
79 +                _snprintf(estr, sizeof(estr),
80 +                                "Invalid mode \"%s\" for win_popen().", type);
81 +                eputs(estr);
82 +                return NULL;
83 +        }
84 +        /* single quotes aren't removed, so change to double-quotes */
85 +        for (s=command; *s; s++)
86 +                if (*s == '\'')
87 +                        *s = '"';
88 +
89          stdoutOrig = GetStdHandle(STD_OUTPUT_HANDLE);
90          stdinOrig = GetStdHandle(STD_INPUT_HANDLE);
91          /* if we have a console, use it for error output */
92          stderrWr = GetStdHandle(STD_ERROR_HANDLE);
93  
94 <        if((ncmds = parse_pipes(command, cmdlines, RAD_MAX_PIPES)) <= 0) {
94 >        ncmds = parse_pipes(command,cmdlines,&infn,&outfn,&append,RAD_MAX_PIPES);
95 >        if(ncmds <= 0) {
96                  eputs("Too many pipes or malformed command.");
97                  goto error;
98          }
99  
100 +        if (infn != NULL) {
101 +                stdoutRd = newFile(infn, mode);
102 +        }
103 +
104          for(n = 0; n < ncmds; ++n) {
105                  if(!createPipes(&stdoutRd, &stdoutWr,
106                          &stdinRd, &stdinWr)) {
107                          eputs("Error creating pipe");
108                          goto error;
109                  }
110 +                if (outfn != NULL && n == ncmds - 1) {
111 +                        CloseHandle(stdoutWr);
112 +                        CloseHandle(stdoutRd);
113 +                        stdoutWr = newFile(outfn, mode);
114 +                }
115 +                if (n == 0 && mode == W_MODE) {
116 +                        /* create a standard C file pointer for writing to the input */
117 +                        inf = _fdopen(_open_osfhandle((long)stdinWr, _O_RDONLY), "w");
118 +                }
119                  /* find the executable on the PATH */
120                  args = nextword(executable, sizeof(executable), cmdlines[n]);
121                  if (args == NULL) {
# Line 86 | Line 124 | char* type
124                  }
125                  execfile = getpath(executable, getenv("PATH"), X_OK);
126                  if(execfile == NULL) {
89                        char estr[512];
127                          _snprintf(estr, sizeof(estr),
128                                          "Can't find executable for \"%s\".", executable);
129                          eputs(estr);
130                          goto error;
131                  }
132                  if(!runChild(execfile, cmdlines[n], stdinRd, stdoutWr, stderrWr)) {
96                        char estr[512];
133                          _snprintf(estr, sizeof(estr),
134                                          "Unable to execute executable \"%s\".", executable);
135                          eputs(estr);
# Line 103 | Line 139 | char* type
139                     or the final read will block */
140                  CloseHandle(stdoutWr);
141          }
142 +
143          /* clean up */
144          resetStdHandles(stdinOrig, stdoutOrig);
145          for (i = 0; i < ncmds; i++) free(cmdlines[i]);
146 +        if (infn != NULL) free(infn);
147 +        if (outfn != NULL) free(outfn);
148  
149 <        /* return a standard C file pointer for reading the output */
150 <        return _fdopen(_open_osfhandle((long)stdoutRd, _O_RDONLY), "r");
149 >        if (mode == R_MODE) {
150 >                /* return a standard C file pointer for reading the output */
151 >                return _fdopen(_open_osfhandle((long)stdoutRd, _O_RDONLY), "r");
152 >        } else if (mode == W_MODE) {
153 >                /* return a standard C file pointer for writing to the input */
154 >                return inf;
155 >        }
156  
157   error:
158          resetStdHandles(stdinOrig, stdoutOrig);
159          for (i = 0; i < ncmds; i++) free(cmdlines[i]);
160 +        if (infn != NULL) free(infn);
161 +        if (outfn != NULL) free(outfn);
162          return NULL;
163   }
164  
165  
166 + HANDLE
167 + newFile(char *fn, int mode)
168 + {
169 +        SECURITY_ATTRIBUTES sAttr;
170 +        HANDLE fh;
171 +
172 +        sAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
173 +        sAttr.bInheritHandle = TRUE;
174 +        sAttr.lpSecurityDescriptor = NULL;
175 +
176 +        if (mode == R_MODE) {
177 +                fh = CreateFile(fn,
178 +                                GENERIC_READ,
179 +                                FILE_SHARE_READ,
180 +                                &sAttr,
181 +                                OPEN_EXISTING,
182 +                                FILE_ATTRIBUTE_NORMAL,
183 +                                NULL);
184 +        } else if (mode == W_MODE || mode == A_MODE) {
185 +                fh = CreateFile(fn,
186 +                                GENERIC_WRITE,
187 +                                FILE_SHARE_WRITE,
188 +                                &sAttr,
189 +                                mode==W_MODE?CREATE_ALWAYS:OPEN_ALWAYS,
190 +                                FILE_ATTRIBUTE_NORMAL,
191 +                                NULL);
192 +        }
193 +        if (fh == NULL) {
194 +                int e = GetLastError();
195 +        }
196 +        return fh;
197 + }
198 +
199 +
200   static BOOL
201   createPipes(       /* establish matching pipes for a subprocess */
202   HANDLE* stdoutRd,
# Line 187 | Line 267 | HANDLE stdinOrig
267  
268   static int
269   parse_pipes(     /* split a shell command pipe sequence */
270 < char* s,
271 < char* lines[],
270 > char *s,
271 > char *lines[],
272 > char **infn,
273 > char **outfn,
274 > int *append,
275   int maxl
276   )
277   {
278          int n = 0, i;
279          char *se, *ws;
280 +        char *curs;
281          int llen = 0;
282          int quote = 0;
283 +        int last = 0;
284  
285          if (maxl<= 0) return 0;
286          if (s == NULL) {
287                  return 0;
288          }
289 +        *infn = *outfn = NULL;
290          while (isspace(*s)) s++; /* leading whitespace */
291          se = s;
292          while (n < maxl) {
# Line 213 | Line 299 | int maxl
299                                  if (quote == '\'') quote = 0;
300                                  else if (quote == 0) quote = '\'';
301                                  break;
302 +                        case '<':
303 +                        case '>':
304                          case '|':
305                          case '\0':
306 <                                if (*se == '|' && quote)
306 >                                if (*se != '\0' && quote)
307                                          break;
308                                  llen = se - s;
309 <                                lines[n] = malloc(llen+1);
310 <                                strncpy(lines[n], s, llen);
309 >                                curs = malloc(llen+1);
310 >                                strncpy(curs, s, llen);
311                                  /* remove unix style line-end escapes */
312 <                                while((ws = strstr(lines[n], "\\\n")) != NULL)
312 >                                while((ws = strstr(curs, "\\\n")) != NULL)
313                                          *ws = *(ws+1) = ' ';
314                                  /* remove DOS style line-end escapes */
315 <                                while((ws = strstr(lines[n], "\\\r\n")) != NULL)
315 >                                while((ws = strstr(curs, "\\\r\n")) != NULL)
316                                          *ws = *(ws+1) = *(ws+2) = ' ';
317 <                                while (isspace(*(lines[n] + llen - 1)))
317 >                                while (isspace(*(curs + llen - 1)))
318                                          llen--; /* trailing whitespace */
319 <                                lines[n][llen] = '\0';
320 <                                n++;
319 >                                curs[llen] = '\0';
320 >
321 >                                if (last == '|' || last == 0) { /* first or pipe */
322 >                                        lines[n] = curs;
323 >                                        n++;
324 >                                        curs = NULL;
325 >                                } else if (last == '<') { /* input file */
326 >                                        if (*infn != NULL) {
327 >                                                eputs("win_popen(): ambiguous input redirection");
328 >                                                goto error;
329 >                                        }
330 >                                        *infn = curs;
331 >                                        curs = NULL;
332 >                                } else if (last == '>') { /* output file */
333 >                                        if (*outfn != NULL) {
334 >                                                eputs("win_popen(): ambiguous output redirection");
335 >                                                goto error;
336 >                                        }
337 >                                        *outfn = curs;
338 >                                        curs = NULL;
339 >                                        if (*se != '\0' && *se+1 == '>') { /* >> */
340 >                                                *append = 1;
341 >                                                se++;
342 >                                        }
343 >                                }
344 >                                last = *se;
345 >
346                                  if (*se == '\0') return n;
347                                  s = se + 1;
348                                  while (isspace(*s)) s++; /* leading whitespace */
# Line 241 | Line 354 | int maxl
354                  se++;
355          }
356          /* more jobs than slots */
357 + error:
358          for (i = 0; i < n; i++) free(lines[i]);
359 +        if (*infn != NULL) free(*infn);
360 +        if (*outfn != NULL) free(*outfn);
361 +        if (curs != NULL) free(curs);
362          return -1;
363   }
364  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines