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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines