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.2 by schorsch, Mon Oct 27 10:19:31 2003 UTC vs.
Revision 1.3 by schorsch, Sun Mar 28 20:33:12 2004 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines