1 # http://thread.gmane.org/gmane.comp.gnu.utils.bugs/13520/
2 # http://thread.gmane.org/gmane.comp.gnu.utils.bugs/12433
3
4 Mon Jul 3 00:27:59 2006 Arnold D. Robbins <arnold @ skeeve.com>
5
6 * io.c (INTERNAL_HANDLE): New constant for use by `iop_alloc'
7 when allocating an internal IOBUF.
8 (pidopen, useropen): Use it.
9 (iop_alloc): Add check for it and just return iop.
10
11 Sun Jun 18 22:27:25 2006 Arnold D. Robbins <arnold @ skeeve.com>
12
13 Repair internal names like /dev/user, /dev/pid, as well as /dev/fd/N,
14 which have been broken for a long time but noone noticed.
15
16 * io.c (is_internal): new macro to check for internal file like `/dev/user'.
17 (spec_setup): Reduce to two parameters, allocate logic is always true.
18 Add IOP_NO_FREE to flag.
19 (pidopen, useropen): Return `IOBUF *' instead of int. Fix
20 logic to test if `iop' parameter is NULL and if so to allocate it.
21 (specfdopen,): Return `IOBUF *' instead of int. Fix
22 logic to test if `iop' parameter is NULL and if so to allocate it.
23 Don't set IOP_NO_FREE in flag.
24 (iop_open): Remove `IOBUF iob' field from `struct internal' and its use
25 and the use of `spec_setup' from the code here. Change the check in the
26 call to the open function to look for NULL.
27 (get_a_record): Use `is_internal' in initial check for filling the
28 buffer to not try to call `read' on internal files. If true, set
29 the IOP_AT_EOF in the flag and return EOF.
30
31 Fri Aug 12 13:10:33 2005 Arnold D. Robbins <arnold @ skeeve.com>
32
33 * io.c (iop_alloc): Only free `iop' if it was malloc'ed in
34 the first place.
35
36 --- ../gawk-3.1.5/io.c 2005-07-26 21:07:43.000000000 +0300
37 +++ io.c 2006-07-03 00:27:51.000000000 +0300
38 @@ -103,6 +103,9 @@
39
40 typedef enum { CLOSE_ALL, CLOSE_TO, CLOSE_FROM } two_way_close_type;
41
42 +/* For internal files, /dev/pid, etc. */
43 +#define INTERNAL_HANDLE (-42)
44 +
45 /* Several macros make the code a bit clearer: */
46 /* */
47 /* */
48 @@ -110,6 +113,7 @@
49 #define at_eof(iop) ((iop->flag & IOP_AT_EOF) != 0)
50 #define has_no_data(iop) (iop->dataend == NULL)
51 #define no_data_left(iop) (iop->off >= iop->dataend)
52 +#define is_internal(iop) ((iop->flag & IOP_IS_INTERNAL) != 0)
53 /* The key point to the design is to split out the code that searches through */
54 /* a buffer looking for the record and the terminator into separate routines, */
55 /* with a higher-level routine doing the reading of data and buffer management. */
56 @@ -163,10 +167,10 @@
57 static int gawk_pclose P((struct redirect *rp));
58 static int do_pathopen P((const char *file));
59 static int str2mode P((const char *mode));
60 -static void spec_setup P((IOBUF *iop, int len, int allocate));
61 -static int specfdopen P((IOBUF *iop, const char *name, const char *mode));
62 -static int pidopen P((IOBUF *iop, const char *name, const char *mode));
63 -static int useropen P((IOBUF *iop, const char *name, const char *mode));
64 +static void spec_setup P((IOBUF *iop, int len));
65 +static IOBUF *specfdopen P((IOBUF *iop, const char *name, const char *mode));
66 +static IOBUF *pidopen P((IOBUF *iop, const char *name, const char *mode));
67 +static IOBUF *useropen P((IOBUF *iop, const char *name, const char *mode));
68 static int two_way_open P((const char *str, struct redirect *rp));
69 static int pty_vs_pipe P((const char *command));
70
71 @@ -1422,30 +1426,24 @@
72 /* spec_setup --- setup an IOBUF for a special internal file */
73
74 static void
75 -spec_setup(IOBUF *iop, int len, int allocate)
76 +spec_setup(IOBUF *iop, int len)
77 {
78 char *cp;
79
80 - if (allocate) {
81 - emalloc(cp, char *, len+2, "spec_setup");
82 - iop->buf = cp;
83 - } else {
84 - len = strlen(iop->buf);
85 - iop->buf[len++] = '\n'; /* get_a_record clobbered it */
86 - iop->buf[len] = '\0'; /* just in case */
87 - }
88 + emalloc(cp, char *, len+2, "spec_setup");
89 + iop->buf = cp;
90 iop->off = iop->buf;
91 iop->count = 0;
92 iop->size = len;
93 iop->end = iop->buf + len;
94 iop->dataend = iop->end;
95 iop->fd = -1;
96 - iop->flag = IOP_IS_INTERNAL | IOP_AT_START;
97 + iop->flag = IOP_IS_INTERNAL | IOP_AT_START | IOP_NO_FREE;
98 }
99
100 /* specfdopen --- open an fd special file */
101
102 -static int
103 +static IOBUF *
104 specfdopen(IOBUF *iop, const char *name, const char *mode)
105 {
106 int fd;
107 @@ -1453,17 +1451,14 @@
108
109 fd = devopen(name, mode);
110 if (fd == INVALID_HANDLE)
111 - return INVALID_HANDLE;
112 - tp = iop_alloc(fd, name, NULL);
113 + return NULL;
114 + tp = iop_alloc(fd, name, iop);
115 if (tp == NULL) {
116 /* don't leak fd's */
117 close(fd);
118 - return INVALID_HANDLE;
119 + return NULL;
120 }
121 - *iop = *tp;
122 - iop->flag |= IOP_NO_FREE;
123 - free(tp);
124 - return 0;
125 + return tp;
126 }
127
128 #ifdef GETPGRP_VOID
129 @@ -1474,7 +1469,7 @@
130
131 /* pidopen --- "open" /dev/pid, /dev/ppid, and /dev/pgrpid */
132
133 -static int
134 +static IOBUF *
135 pidopen(IOBUF *iop, const char *name, const char *mode ATTRIBUTE_UNUSED)
136 {
137 char tbuf[BUFSIZ];
138 @@ -1483,6 +1478,12 @@
139
140 warning(_("use `PROCINFO[\"%s\"]' instead of `%s'"), cp, name);
141
142 + if (iop == NULL) {
143 + iop = iop_alloc(INTERNAL_HANDLE, name, iop);
144 + if (iop == NULL)
145 + return NULL;
146 + }
147 +
148 if (name[6] == 'g')
149 sprintf(tbuf, "%d\n", (int) getpgrp(getpgrp_arg()));
150 else if (name[6] == 'i')
151 @@ -1490,9 +1491,9 @@
152 else
153 sprintf(tbuf, "%d\n", (int) getppid());
154 i = strlen(tbuf);
155 - spec_setup(iop, i, TRUE);
156 + spec_setup(iop, i);
157 strcpy(iop->buf, tbuf);
158 - return 0;
159 + return iop;
160 }
161
162 /* useropen --- "open" /dev/user */
163 @@ -1507,7 +1508,7 @@
164 * supplementary group set.
165 */
166
167 -static int
168 +static IOBUF *
169 useropen(IOBUF *iop, const char *name ATTRIBUTE_UNUSED, const char *mode ATTRIBUTE_UNUSED)
170 {
171 char tbuf[BUFSIZ], *cp;
172 @@ -1515,6 +1516,12 @@
173
174 warning(_("use `PROCINFO[...]' instead of `/dev/user'"));
175
176 + if (iop == NULL) {
177 + iop = iop_alloc(INTERNAL_HANDLE, name, iop);
178 + if (iop == NULL)
179 + return NULL;
180 + }
181 +
182 sprintf(tbuf, "%d %d %d %d", (int) getuid(), (int) geteuid(), (int) getgid(), (int) getegid());
183
184 cp = tbuf + strlen(tbuf);
185 @@ -1529,9 +1536,9 @@
186 *cp++ = '\0';
187
188 i = strlen(tbuf);
189 - spec_setup(iop, i, TRUE);
190 + spec_setup(iop, i);
191 strcpy(iop->buf, tbuf);
192 - return 0;
193 + return iop;
194 }
195
196 /* iop_open --- handle special and regular files for input */
197 @@ -1544,8 +1551,7 @@
198 static struct internal {
199 const char *name;
200 int compare;
201 - int (*fp) P((IOBUF *, const char *, const char *));
202 - IOBUF iob;
203 + IOBUF *(*fp) P((IOBUF *, const char *, const char *));
204 } table[] = {
205 { "/dev/fd/", 8, specfdopen },
206 { "/dev/stdin", 10, specfdopen },
207 @@ -1570,12 +1576,7 @@
208
209 for (i = 0; i < devcount; i++) {
210 if (STREQN(name, table[i].name, table[i].compare)) {
211 - iop = & table[i].iob;
212 -
213 - if (iop->buf != NULL) {
214 - spec_setup(iop, 0, FALSE);
215 - return iop;
216 - } else if ((*table[i].fp)(iop, name, mode) == 0)
217 + if ((iop = (*table[i].fp)(iop, name, mode)) != NULL)
218 return iop;
219 else {
220 warning(_("could not open `%s', mode `%s'"),
221 @@ -2480,9 +2481,12 @@
222 {
223 struct stat sbuf;
224 struct open_hook *oh;
225 + int iop_malloced = FALSE;
226
227 - if (iop == NULL)
228 + if (iop == NULL) {
229 emalloc(iop, IOBUF *, sizeof(IOBUF), "iop_alloc");
230 + iop_malloced = TRUE;
231 + }
232 memset(iop, '\0', sizeof(IOBUF));
233 iop->flag = 0;
234 iop->fd = fd;
235 @@ -2494,8 +2498,12 @@
236 break;
237 }
238
239 + if (iop->fd == INTERNAL_HANDLE)
240 + return iop;
241 +
242 if (iop->fd == INVALID_HANDLE) {
243 - free(iop);
244 + if (iop_malloced)
245 + free(iop);
246 return NULL;
247 }
248 if (isatty(iop->fd))
249 @@ -2503,7 +2511,7 @@
250 iop->readsize = iop->size = optimal_bufsize(iop->fd, & sbuf);
251 iop->sbuf = sbuf;
252 if (do_lint && S_ISREG(sbuf.st_mode) && sbuf.st_size == 0)
253 - lintwarn(_("data file `%s' is empty"), name);
254 + lintwarn(_("data file `%s' is empty"), name);
255 errno = 0;
256 iop->count = iop->scanoff = 0;
257 emalloc(iop->buf, char *, iop->size += 2, "iop_alloc");
258 @@ -2906,6 +2914,10 @@
259
260 /* <fill initial buffer>= */
261 if (has_no_data(iop) || no_data_left(iop)) {
262 + if (is_internal(iop)) {
263 + iop->flag |= IOP_AT_EOF;
264 + return EOF;
265 + }
266 iop->count = read(iop->fd, iop->buf, iop->readsize);
267 if (iop->count == 0) {
268 iop->flag |= IOP_AT_EOF;
|