Lines 39-63
Link Here
|
39 |
* HeDu (hedu@cul-ipn.uni-kiel.de) 4/94 |
39 |
* HeDu (hedu@cul-ipn.uni-kiel.de) 4/94 |
40 |
*/ |
40 |
*/ |
41 |
|
41 |
|
|
|
42 |
/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ |
43 |
|
42 |
#include "XpmI.h" |
44 |
#include "XpmI.h" |
43 |
#include <ctype.h> |
45 |
#include <ctype.h> |
|
|
46 |
#include <string.h> |
44 |
|
47 |
|
45 |
#ifdef HAS_STRLCAT |
48 |
#ifdef HAS_STRLCAT |
46 |
# define STRLCAT(dst, src, dstsize) { \ |
49 |
# define STRLCAT(dst, src, dstsize) do { \ |
47 |
if (strlcat(dst, src, dstsize) >= (dstsize)) \ |
50 |
if (strlcat(dst, src, dstsize) >= (dstsize)) \ |
48 |
return (XpmFileInvalid); } |
51 |
return (XpmFileInvalid); } while(0) |
49 |
# define STRLCPY(dst, src, dstsize) { \ |
52 |
# define STRLCPY(dst, src, dstsize) do { \ |
50 |
if (strlcpy(dst, src, dstsize) >= (dstsize)) \ |
53 |
if (strlcpy(dst, src, dstsize) >= (dstsize)) \ |
51 |
return (XpmFileInvalid); } |
54 |
return (XpmFileInvalid); } while(0) |
52 |
#else |
55 |
#else |
53 |
# define STRLCAT(dst, src, dstsize) { \ |
56 |
# define STRLCAT(dst, src, dstsize) do { \ |
54 |
if ((strlen(dst) + strlen(src)) < (dstsize)) \ |
57 |
if ((strlen(dst) + strlen(src)) < (dstsize)) \ |
55 |
strcat(dst, src); \ |
58 |
strcat(dst, src); \ |
56 |
else return (XpmFileInvalid); } |
59 |
else return (XpmFileInvalid); } while(0) |
57 |
# define STRLCPY(dst, src, dstsize) { \ |
60 |
# define STRLCPY(dst, src, dstsize) do { \ |
58 |
if (strlen(src) < (dstsize)) \ |
61 |
if (strlen(src) < (dstsize)) \ |
59 |
strcpy(dst, src); \ |
62 |
strcpy(dst, src); \ |
60 |
else return (XpmFileInvalid); } |
63 |
else return (XpmFileInvalid); } while(0) |
61 |
#endif |
64 |
#endif |
62 |
|
65 |
|
63 |
LFUNC(ParsePixels, int, (xpmData *data, unsigned int width, |
66 |
LFUNC(ParsePixels, int, (xpmData *data, unsigned int width, |
Lines 77-82
Link Here
|
77 |
/* function call in case of error, frees only locally allocated variables */ |
80 |
/* function call in case of error, frees only locally allocated variables */ |
78 |
#undef RETURN |
81 |
#undef RETURN |
79 |
#define RETURN(status) \ |
82 |
#define RETURN(status) \ |
|
|
83 |
do \ |
80 |
{ \ |
84 |
{ \ |
81 |
if (colorTable) xpmFreeColorTable(colorTable, ncolors); \ |
85 |
if (colorTable) xpmFreeColorTable(colorTable, ncolors); \ |
82 |
if (pixelindex) XpmFree(pixelindex); \ |
86 |
if (pixelindex) XpmFree(pixelindex); \ |
Lines 84-90
Link Here
|
84 |
if (colors_cmt) XpmFree(colors_cmt); \ |
88 |
if (colors_cmt) XpmFree(colors_cmt); \ |
85 |
if (pixels_cmt) XpmFree(pixels_cmt); \ |
89 |
if (pixels_cmt) XpmFree(pixels_cmt); \ |
86 |
return(status); \ |
90 |
return(status); \ |
87 |
} |
91 |
} while(0) |
88 |
|
92 |
|
89 |
/* |
93 |
/* |
90 |
* This function parses an Xpm file or data and store the found informations |
94 |
* This function parses an Xpm file or data and store the found informations |
Lines 182-188
Link Here
|
182 |
/* |
186 |
/* |
183 |
* parse extensions |
187 |
* parse extensions |
184 |
*/ |
188 |
*/ |
185 |
if (info && (info->valuemask & XpmReturnExtensions)) |
189 |
if (info && (info->valuemask & XpmReturnExtensions)) { |
186 |
if (extensions) { |
190 |
if (extensions) { |
187 |
ErrorStatus = xpmParseExtensions(data, &info->extensions, |
191 |
ErrorStatus = xpmParseExtensions(data, &info->extensions, |
188 |
&info->nextensions); |
192 |
&info->nextensions); |
Lines 192-197
Link Here
|
192 |
info->extensions = NULL; |
196 |
info->extensions = NULL; |
193 |
info->nextensions = 0; |
197 |
info->nextensions = 0; |
194 |
} |
198 |
} |
|
|
199 |
} |
195 |
|
200 |
|
196 |
/* |
201 |
/* |
197 |
* store found informations in the XpmImage structure |
202 |
* store found informations in the XpmImage structure |
Lines 347-353
Link Here
|
347 |
char **defaults; |
352 |
char **defaults; |
348 |
int ErrorStatus; |
353 |
int ErrorStatus; |
349 |
|
354 |
|
350 |
if (ncolors >= SIZE_MAX / sizeof(XpmColor)) |
355 |
if (ncolors >= UINT_MAX / sizeof(XpmColor)) |
351 |
return (XpmNoMemory); |
356 |
return (XpmNoMemory); |
352 |
colorTable = (XpmColor *) XpmCalloc(ncolors, sizeof(XpmColor)); |
357 |
colorTable = (XpmColor *) XpmCalloc(ncolors, sizeof(XpmColor)); |
353 |
if (!colorTable) |
358 |
if (!colorTable) |
Lines 360-366
Link Here
|
360 |
/* |
365 |
/* |
361 |
* read pixel value |
366 |
* read pixel value |
362 |
*/ |
367 |
*/ |
363 |
if (cpp >= SIZE_MAX - 1) { |
368 |
if (cpp >= UINT_MAX - 1) { |
364 |
xpmFreeColorTable(colorTable, ncolors); |
369 |
xpmFreeColorTable(colorTable, ncolors); |
365 |
return (XpmNoMemory); |
370 |
return (XpmNoMemory); |
366 |
} |
371 |
} |
Lines 419-427
Link Here
|
419 |
return (XpmFileInvalid); |
424 |
return (XpmFileInvalid); |
420 |
} |
425 |
} |
421 |
if (!lastwaskey) |
426 |
if (!lastwaskey) |
422 |
STRLCAT(curbuf, " ", sizeof(curbuf)); /* append space */ |
427 |
STRLCAT(curbuf, " ", sizeof(curbuf));/* append space */ |
423 |
buf[l] = '\0'; |
428 |
buf[l] = '\0'; |
424 |
STRLCAT(curbuf, buf, sizeof(curbuf));/* append buf */ |
429 |
STRLCAT(curbuf, buf, sizeof(curbuf)); /* append buf */ |
425 |
lastwaskey = 0; |
430 |
lastwaskey = 0; |
426 |
} |
431 |
} |
427 |
} |
432 |
} |
Lines 429-435
Link Here
|
429 |
xpmFreeColorTable(colorTable, ncolors); |
434 |
xpmFreeColorTable(colorTable, ncolors); |
430 |
return (XpmFileInvalid); |
435 |
return (XpmFileInvalid); |
431 |
} |
436 |
} |
432 |
len = strlen(curbuf) + 1; |
437 |
len = strlen(curbuf) + 1; /* integer overflow just theoretically possible */ |
433 |
s = defaults[curkey] = (char *) XpmMalloc(len); |
438 |
s = defaults[curkey] = (char *) XpmMalloc(len); |
434 |
if (!s) { |
439 |
if (!s) { |
435 |
xpmFreeColorTable(colorTable, ncolors); |
440 |
xpmFreeColorTable(colorTable, ncolors); |
Lines 448-454
Link Here
|
448 |
/* |
453 |
/* |
449 |
* read pixel value |
454 |
* read pixel value |
450 |
*/ |
455 |
*/ |
451 |
if (cpp >= SIZE_MAX - 1) { |
456 |
if (cpp >= UINT_MAX - 1) { |
452 |
xpmFreeColorTable(colorTable, ncolors); |
457 |
xpmFreeColorTable(colorTable, ncolors); |
453 |
return (XpmNoMemory); |
458 |
return (XpmNoMemory); |
454 |
} |
459 |
} |
Lines 493-499
Link Here
|
493 |
memcpy(s, curbuf, len); |
498 |
memcpy(s, curbuf, len); |
494 |
color->c_color = s; |
499 |
color->c_color = s; |
495 |
*curbuf = '\0'; /* reset curbuf */ |
500 |
*curbuf = '\0'; /* reset curbuf */ |
496 |
if (a < ncolors - 1) |
501 |
if (a < ncolors - 1) /* can we trust ncolors -> leave data's bounds */ |
497 |
xpmNextString(data); /* get to the next string */ |
502 |
xpmNextString(data); /* get to the next string */ |
498 |
} |
503 |
} |
499 |
} |
504 |
} |
Lines 512-522
Link Here
|
512 |
xpmHashTable *hashtable; |
517 |
xpmHashTable *hashtable; |
513 |
unsigned int **pixels; |
518 |
unsigned int **pixels; |
514 |
{ |
519 |
{ |
515 |
unsigned int *iptr, *iptr2; |
520 |
unsigned int *iptr, *iptr2 = NULL; /* found by Egbert Eich */ |
516 |
unsigned int a, x, y; |
521 |
unsigned int a, x, y; |
517 |
|
522 |
|
518 |
if ((height > 0 && width >= SIZE_MAX / height) || |
523 |
if ((height > 0 && width >= UINT_MAX / height) || |
519 |
width * height >= SIZE_MAX / sizeof(unsigned int)) |
524 |
width * height >= UINT_MAX / sizeof(unsigned int)) |
520 |
return XpmNoMemory; |
525 |
return XpmNoMemory; |
521 |
#ifndef FOR_MSW |
526 |
#ifndef FOR_MSW |
522 |
iptr2 = (unsigned int *) XpmMalloc(sizeof(unsigned int) * width * height); |
527 |
iptr2 = (unsigned int *) XpmMalloc(sizeof(unsigned int) * width * height); |
Lines 541-548
Link Here
|
541 |
{ |
546 |
{ |
542 |
unsigned short colidx[256]; |
547 |
unsigned short colidx[256]; |
543 |
|
548 |
|
544 |
if (ncolors > 256) |
549 |
if (ncolors > 256) { |
545 |
return (XpmFileInvalid); |
550 |
return (XpmFileInvalid); |
|
|
551 |
XpmFree(iptr2); /* found by Egbert Eich */ |
552 |
} |
546 |
|
553 |
|
547 |
bzero((char *)colidx, 256 * sizeof(short)); |
554 |
bzero((char *)colidx, 256 * sizeof(short)); |
548 |
for (a = 0; a < ncolors; a++) |
555 |
for (a = 0; a < ncolors; a++) |
Lines 569-584
Link Here
|
569 |
{ |
576 |
{ |
570 |
|
577 |
|
571 |
/* free all allocated pointers at all exits */ |
578 |
/* free all allocated pointers at all exits */ |
572 |
#define FREE_CIDX {int f; for (f = 0; f < 256; f++) \ |
579 |
#define FREE_CIDX \ |
573 |
if (cidx[f]) XpmFree(cidx[f]);} |
580 |
do \ |
|
|
581 |
{ \ |
582 |
int f; for (f = 0; f < 256; f++) \ |
583 |
if (cidx[f]) XpmFree(cidx[f]); \ |
584 |
} while(0) |
574 |
|
585 |
|
575 |
/* array of pointers malloced by need */ |
586 |
/* array of pointers malloced by need */ |
576 |
unsigned short *cidx[256]; |
587 |
unsigned short *cidx[256]; |
577 |
int char1; |
588 |
unsigned int char1; |
578 |
|
589 |
|
579 |
bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */ |
590 |
bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */ |
580 |
for (a = 0; a < ncolors; a++) { |
591 |
for (a = 0; a < ncolors; a++) { |
581 |
char1 = colorTable[a].string[0]; |
592 |
char1 = (unsigned char) colorTable[a].string[0]; |
582 |
if (cidx[char1] == NULL) { /* get new memory */ |
593 |
if (cidx[char1] == NULL) { /* get new memory */ |
583 |
cidx[char1] = (unsigned short *) |
594 |
cidx[char1] = (unsigned short *) |
584 |
XpmCalloc(256, sizeof(unsigned short)); |
595 |
XpmCalloc(256, sizeof(unsigned short)); |
Lines 597-603
Link Here
|
597 |
int cc1 = xpmGetC(data); |
608 |
int cc1 = xpmGetC(data); |
598 |
if (cc1 > 0 && cc1 < 256) { |
609 |
if (cc1 > 0 && cc1 < 256) { |
599 |
int cc2 = xpmGetC(data); |
610 |
int cc2 = xpmGetC(data); |
600 |
if (cc2 > 0 && cc2 < 256 && cidx[cc1][cc2] != 0) |
611 |
if (cc2 > 0 && cc2 < 256 && cidx[cc1] && cidx[cc1][cc2] != 0) |
601 |
*iptr = cidx[cc1][cc2] - 1; |
612 |
*iptr = cidx[cc1][cc2] - 1; |
602 |
else { |
613 |
else { |
603 |
FREE_CIDX; |
614 |
FREE_CIDX; |
Lines 621-628
Link Here
|
621 |
char *s; |
632 |
char *s; |
622 |
char buf[BUFSIZ]; |
633 |
char buf[BUFSIZ]; |
623 |
|
634 |
|
624 |
if (cpp >= sizeof(buf)) |
635 |
if (cpp >= sizeof(buf)) { |
625 |
return (XpmFileInvalid); |
636 |
return (XpmFileInvalid); |
|
|
637 |
XpmFree(iptr2); /* found by Egbert Eich */ |
638 |
} |
626 |
|
639 |
|
627 |
buf[cpp] = '\0'; |
640 |
buf[cpp] = '\0'; |
628 |
if (USE_HASHTABLE) { |
641 |
if (USE_HASHTABLE) { |
Lines 632-638
Link Here
|
632 |
xpmNextString(data); |
645 |
xpmNextString(data); |
633 |
for (x = 0; x < width; x++, iptr++) { |
646 |
for (x = 0; x < width; x++, iptr++) { |
634 |
for (a = 0, s = buf; a < cpp; a++, s++) |
647 |
for (a = 0, s = buf; a < cpp; a++, s++) |
635 |
*s = xpmGetC(data); |
648 |
*s = xpmGetC(data); /* int assigned to char, not a problem here */ |
636 |
slot = xpmHashSlot(hashtable, buf); |
649 |
slot = xpmHashSlot(hashtable, buf); |
637 |
if (!*slot) { /* no color matches */ |
650 |
if (!*slot) { /* no color matches */ |
638 |
XpmFree(iptr2); |
651 |
XpmFree(iptr2); |
Lines 646-652
Link Here
|
646 |
xpmNextString(data); |
659 |
xpmNextString(data); |
647 |
for (x = 0; x < width; x++, iptr++) { |
660 |
for (x = 0; x < width; x++, iptr++) { |
648 |
for (a = 0, s = buf; a < cpp; a++, s++) |
661 |
for (a = 0, s = buf; a < cpp; a++, s++) |
649 |
*s = xpmGetC(data); |
662 |
*s = xpmGetC(data); /* int assigned to char, not a problem here */ |
650 |
for (a = 0; a < ncolors; a++) |
663 |
for (a = 0; a < ncolors; a++) |
651 |
if (!strcmp(colorTable[a].string, buf)) |
664 |
if (!strcmp(colorTable[a].string, buf)) |
652 |
break; |
665 |
break; |
Lines 701-707
Link Here
|
701 |
while (!notstart && notend) { |
714 |
while (!notstart && notend) { |
702 |
/* there starts an extension */ |
715 |
/* there starts an extension */ |
703 |
ext = (XpmExtension *) |
716 |
ext = (XpmExtension *) |
704 |
XpmRealloc(exts, (num + 1) * sizeof(XpmExtension)); |
717 |
XpmRealloc(exts, (num + 1) * sizeof(XpmExtension)); /* can the loop be forced to iterate often enough to make "(num + 1) * sizeof(XpmExtension)" wrapping? */ |
705 |
if (!ext) { |
718 |
if (!ext) { |
706 |
XpmFree(string); |
719 |
XpmFree(string); |
707 |
XpmFreeExtensions(exts, num); |
720 |
XpmFreeExtensions(exts, num); |
Lines 738-744
Link Here
|
738 |
while ((notstart = strncmp("XPMEXT", string, 6)) |
751 |
while ((notstart = strncmp("XPMEXT", string, 6)) |
739 |
&& (notend = strncmp("XPMENDEXT", string, 9))) { |
752 |
&& (notend = strncmp("XPMENDEXT", string, 9))) { |
740 |
sp = (char **) |
753 |
sp = (char **) |
741 |
XpmRealloc(ext->lines, (nlines + 1) * sizeof(char *)); |
754 |
XpmRealloc(ext->lines, (nlines + 1) * sizeof(char *)); /* can we iterate enough for a wrapping? */ |
742 |
if (!sp) { |
755 |
if (!sp) { |
743 |
XpmFree(string); |
756 |
XpmFree(string); |
744 |
ext->nlines = nlines; |
757 |
ext->nlines = nlines; |
745 |
-- /dev/null |
|
|
Line 0
Link Here
|
|
|
1 |
/* |
2 |
* Copyright (C) 2004 The X.Org fundation |
3 |
* |
4 |
* Permission is hereby granted, free of charge, to any person |
5 |
* obtaining a copy of this software and associated documentation |
6 |
* files (the "Software"), to deal in the Software without |
7 |
* restriction, including without limitation the rights to use, copy, |
8 |
* modify, merge, publish, distribute, sublicense, and/or sell copies |
9 |
* of the Software, and to permit persons to whom the Software is fur- |
10 |
* nished to do so, subject to the following conditions: |
11 |
* |
12 |
* The above copyright notice and this permission notice shall be |
13 |
* included in all copies or substantial portions of the Software. |
14 |
* |
15 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
16 |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
17 |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
18 |
* NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR |
19 |
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
20 |
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
21 |
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
22 |
* |
23 |
* Except as contained in this notice, the name of the X.Org fundation |
24 |
* shall not be used in advertising or otherwise to promote the sale, |
25 |
* use or other dealings in this Software without prior written |
26 |
* authorization from the X.Org fundation. |
27 |
*/ |
28 |
|
29 |
/* |
30 |
** This is a secure but NOT 100% compatible replacement for popen() |
31 |
** Note: - don't use pclose() use fclose() for closing the returned |
32 |
** filedesc.!!! |
33 |
** |
34 |
** Known Bugs: - unable to use i/o-redirection like > or < |
35 |
** Author: - Thomas Biege <thomas@suse.de> |
36 |
** Credits: - Andreas Pfaller <a.pfaller@pop.gun.de> for fixing a SEGV when |
37 |
** calling strtok() |
38 |
*/ |
39 |
|
40 |
#include <sys/types.h> |
41 |
#include <sys/wait.h> |
42 |
#include <stdio.h> |
43 |
#include <stdlib.h> |
44 |
#include <unistd.h> |
45 |
#include <string.h> |
46 |
#include "XpmI.h" |
47 |
|
48 |
#define __SEC_POPEN_TOKEN " " |
49 |
|
50 |
FILE *s_popen(char *cmd, const char *type) |
51 |
{ |
52 |
pid_t pid; |
53 |
int pfd[2]; |
54 |
int rpipe = 0, wpipe = 0, i; |
55 |
char **argv; |
56 |
char *ptr; |
57 |
char *cmdcpy; |
58 |
|
59 |
|
60 |
if(cmd == NULL || cmd == "") |
61 |
return(NULL); |
62 |
|
63 |
if(type[0] != 'r' && type[0] != 'w') |
64 |
return(NULL); |
65 |
|
66 |
if ((cmdcpy = strdup(cmd)) == NULL) |
67 |
return(NULL); |
68 |
|
69 |
argv = NULL; |
70 |
if( (ptr = strtok(cmdcpy, __SEC_POPEN_TOKEN)) == NULL) |
71 |
{ |
72 |
free(cmdcpy); |
73 |
return(NULL); |
74 |
} |
75 |
|
76 |
for(i = 0;; i++) |
77 |
{ |
78 |
if( ( argv = (char **) realloc(argv, (i+1) * sizeof(char *)) ) == NULL) |
79 |
{ |
80 |
free(cmdcpy); |
81 |
return(NULL); |
82 |
} |
83 |
|
84 |
if( (*(argv+i) = (char *) malloc((strlen(ptr)+1) * sizeof(char))) == NULL) |
85 |
{ |
86 |
free(cmdcpy); |
87 |
return(NULL); |
88 |
} |
89 |
|
90 |
strcpy(argv[i], ptr); |
91 |
|
92 |
if( (ptr = strtok(NULL, __SEC_POPEN_TOKEN)) == NULL) |
93 |
{ |
94 |
if( ( argv = (char **) realloc(argv, (i+2) * sizeof(char *))) == NULL) |
95 |
{ |
96 |
free(cmdcpy); |
97 |
return(NULL); |
98 |
} |
99 |
argv[i+1] = NULL; |
100 |
break; |
101 |
} |
102 |
} |
103 |
|
104 |
|
105 |
if(type[0] == 'r') |
106 |
rpipe = 1; |
107 |
else |
108 |
wpipe = 1; |
109 |
|
110 |
if (pipe(pfd) < 0) |
111 |
{ |
112 |
free(cmdcpy); |
113 |
return(NULL); |
114 |
} |
115 |
|
116 |
if((pid = fork()) < 0) |
117 |
{ |
118 |
close(pfd[0]); |
119 |
close(pfd[1]); |
120 |
free(cmdcpy); |
121 |
return(NULL); |
122 |
} |
123 |
|
124 |
if(pid == 0) /* child */ |
125 |
{ |
126 |
if((pid = fork()) < 0) |
127 |
{ |
128 |
close(pfd[0]); |
129 |
close(pfd[1]); |
130 |
free(cmdcpy); |
131 |
return(NULL); |
132 |
} |
133 |
if(pid > 0) |
134 |
{ |
135 |
exit(0); /* child nr. 1 exits */ |
136 |
} |
137 |
|
138 |
/* child nr. 2 */ |
139 |
if(rpipe) |
140 |
{ |
141 |
close(pfd[0]); /* close reading end, we don't need it */ |
142 |
dup2(STDOUT_FILENO, STDERR_FILENO); |
143 |
if (pfd[1] != STDOUT_FILENO) |
144 |
dup2(pfd[1], STDOUT_FILENO); /* redirect stdout to writing end of pipe */ |
145 |
} |
146 |
else |
147 |
{ |
148 |
close(pfd[1]); /* close writing end, we don't need it */ |
149 |
if (pfd[0] != STDIN_FILENO) |
150 |
dup2(pfd[0], STDIN_FILENO); /* redirect stdin to reading end of pipe */ |
151 |
} |
152 |
|
153 |
if(strchr(argv[0], '/') == NULL) |
154 |
execvp(argv[0], argv); /* search in $PATH */ |
155 |
else |
156 |
execv(argv[0], argv); |
157 |
|
158 |
close(pfd[0]); |
159 |
close(pfd[1]); |
160 |
free(cmdcpy); |
161 |
return(NULL); /* exec failed.. ooops! */ |
162 |
} |
163 |
else /* parent */ |
164 |
{ |
165 |
waitpid(pid, NULL, 0); /* wait for child nr. 1 */ |
166 |
|
167 |
if(rpipe) |
168 |
{ |
169 |
close(pfd[1]); |
170 |
free(cmdcpy); |
171 |
return(fdopen(pfd[0], "r")); |
172 |
} |
173 |
else |
174 |
{ |
175 |
close(pfd[0]); |
176 |
free(cmdcpy); |
177 |
return(fdopen(pfd[1], "w")); |
178 |
} |
179 |
|
180 |
} |
181 |
} |
182 |
|