]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/file/src/compress.c
MFC r308420: MFV r308392: file 5.29.
[FreeBSD/stable/10.git] / contrib / file / src / compress.c
1 /*
2  * Copyright (c) Ian F. Darwin 1986-1995.
3  * Software written by Ian F. Darwin and others;
4  * maintained 1995-present by Christos Zoulas and others.
5  * 
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice immediately at the beginning of the file, without modification,
11  *    this list of conditions, and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *  
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 /*
29  * compress routines:
30  *      zmagic() - returns 0 if not recognized, uncompresses and prints
31  *                 information if recognized
32  *      uncompress(method, old, n, newch) - uncompress old into new, 
33  *                                          using method, return sizeof new
34  */
35 #include "file.h"
36
37 #ifndef lint
38 FILE_RCSID("@(#)$File: compress.c,v 1.100 2016/10/24 18:02:17 christos Exp $")
39 #endif
40
41 #include "magic.h"
42 #include <stdlib.h>
43 #ifdef HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
46 #include <string.h>
47 #include <errno.h>
48 #include <ctype.h>
49 #include <stdarg.h>
50 #ifdef HAVE_SIGNAL_H
51 #include <signal.h>
52 # ifndef HAVE_SIG_T
53 typedef void (*sig_t)(int);
54 # endif /* HAVE_SIG_T */
55 #endif 
56 #if !defined(__MINGW32__) && !defined(WIN32)
57 #include <sys/ioctl.h>
58 #endif
59 #ifdef HAVE_SYS_WAIT_H
60 #include <sys/wait.h>
61 #endif
62 #if defined(HAVE_SYS_TIME_H)
63 #include <sys/time.h>
64 #endif
65 #if defined(HAVE_ZLIB_H)
66 #define BUILTIN_DECOMPRESS
67 #include <zlib.h>
68 #endif
69 #ifdef DEBUG
70 int tty = -1;
71 #define DPRINTF(...)    do { \
72         if (tty == -1) \
73                 tty = open("/dev/tty", O_RDWR); \
74         if (tty == -1) \
75                 abort(); \
76         dprintf(tty, __VA_ARGS__); \
77 } while (/*CONSTCOND*/0)
78 #else
79 #define DPRINTF(...)
80 #endif
81
82 #ifdef ZLIBSUPPORT
83 /*
84  * The following python code is not really used because ZLIBSUPPORT is only
85  * defined if we have a built-in zlib, and the built-in zlib handles that.
86  */
87 static const char zlibcode[] =
88     "import sys, zlib; sys.stdout.write(zlib.decompress(sys.stdin.read()))";
89
90 static const char *zlib_args[] = { "python", "-c", zlibcode, NULL };
91
92 static int
93 zlibcmp(const unsigned char *buf)
94 {
95         unsigned short x = 1;
96         unsigned char *s = (unsigned char *)&x;
97
98         if ((buf[0] & 0xf) != 8 || (buf[0] & 0x80) != 0)
99                 return 0;
100         if (s[0] != 1)  /* endianness test */
101                 x = buf[0] | (buf[1] << 8);
102         else
103                 x = buf[1] | (buf[0] << 8);
104         if (x % 31)
105                 return 0;
106         return 1;
107 }
108 #endif
109
110 #define gzip_flags "-cd"
111 #define lrzip_flags "-do"
112 #define lzip_flags gzip_flags
113
114 static const char *gzip_args[] = {
115         "gzip", gzip_flags, NULL
116 };
117 static const char *uncompress_args[] = {
118         "uncompress", "-c", NULL
119 };
120 static const char *bzip2_args[] = {
121         "bzip2", "-cd", NULL
122 };
123 static const char *lzip_args[] = {
124         "lzip", lzip_flags, NULL
125 };
126 static const char *xz_args[] = {
127         "xz", "-cd", NULL
128 };
129 static const char *lrzip_args[] = {
130         "lrzip", lrzip_flags, NULL
131 };
132 static const char *lz4_args[] = {
133         "lz4", "-cd", NULL
134 };
135 static const char *zstd_args[] = {
136         "zstd", "-cd", NULL
137 };
138
139 private const struct {
140         const void *magic;
141         size_t maglen;
142         const char **argv;
143 } compr[] = {
144         { "\037\235",   2, gzip_args },         /* compressed */
145         /* Uncompress can get stuck; so use gzip first if we have it
146          * Idea from Damien Clark, thanks! */
147         { "\037\235",   2, uncompress_args },   /* compressed */
148         { "\037\213",   2, gzip_args },         /* gzipped */
149         { "\037\236",   2, gzip_args },         /* frozen */
150         { "\037\240",   2, gzip_args },         /* SCO LZH */
151         /* the standard pack utilities do not accept standard input */
152         { "\037\036",   2, gzip_args },         /* packed */
153         { "PK\3\4",     4, gzip_args },         /* pkzipped, */
154         /* ...only first file examined */
155         { "BZh",        3, bzip2_args },        /* bzip2-ed */
156         { "LZIP",       4, lzip_args },         /* lzip-ed */
157         { "\3757zXZ\0", 6, xz_args },           /* XZ Utils */
158         { "LRZI",       4, lrzip_args },        /* LRZIP */
159         { "\004\"M\030",4, lz4_args },          /* LZ4 */
160         { "\x28\xB5\x2F\xFD", 4, zstd_args },   /* zstd */
161 #ifdef ZLIBSUPPORT
162         { RCAST(const void *, zlibcmp), 0, zlib_args },         /* zlib */
163 #endif
164 };
165
166 #define OKDATA  0
167 #define NODATA  1
168 #define ERRDATA 2
169
170 private ssize_t swrite(int, const void *, size_t);
171 #if HAVE_FORK
172 private size_t ncompr = sizeof(compr) / sizeof(compr[0]);
173 private int uncompressbuf(int, size_t, size_t, const unsigned char *,
174     unsigned char **, size_t *);
175 #ifdef BUILTIN_DECOMPRESS
176 private int uncompresszlib(const unsigned char *, unsigned char **, size_t,
177     size_t *, int);
178 private int uncompressgzipped(const unsigned char *, unsigned char **, size_t,
179     size_t *);
180 #endif
181 static int makeerror(unsigned char **, size_t *, const char *, ...)
182     __attribute__((__format__(__printf__, 3, 4)));
183 private const char *methodname(size_t);
184
185 protected int
186 file_zmagic(struct magic_set *ms, int fd, const char *name,
187     const unsigned char *buf, size_t nbytes)
188 {
189         unsigned char *newbuf = NULL;
190         size_t i, nsz;
191         char *rbuf;
192         file_pushbuf_t *pb;
193         int urv, prv, rv = 0;
194         int mime = ms->flags & MAGIC_MIME;
195 #ifdef HAVE_SIGNAL_H
196         sig_t osigpipe;
197 #endif
198
199         if ((ms->flags & MAGIC_COMPRESS) == 0)
200                 return 0;
201
202 #ifdef HAVE_SIGNAL_H
203         osigpipe = signal(SIGPIPE, SIG_IGN);
204 #endif
205         for (i = 0; i < ncompr; i++) {
206                 int zm;
207                 if (nbytes < compr[i].maglen)
208                         continue;
209 #ifdef ZLIBSUPPORT
210                 if (compr[i].maglen == 0)
211                         zm = (RCAST(int (*)(const unsigned char *),
212                             CCAST(void *, compr[i].magic)))(buf);
213                 else
214 #endif
215                         zm = memcmp(buf, compr[i].magic, compr[i].maglen) == 0;
216
217                 if (!zm)
218                         continue;
219                 nsz = nbytes;
220                 urv = uncompressbuf(fd, ms->bytes_max, i, buf, &newbuf, &nsz);
221                 DPRINTF("uncompressbuf = %d, %s, %zu\n", urv, (char *)newbuf,
222                     nsz);
223                 switch (urv) {
224                 case OKDATA:
225                 case ERRDATA:
226                         
227                         ms->flags &= ~MAGIC_COMPRESS;
228                         if (urv == ERRDATA)
229                                 prv = file_printf(ms, "%s ERROR: %s",
230                                     methodname(i), newbuf);
231                         else
232                                 prv = file_buffer(ms, -1, name, newbuf, nsz);
233                         if (prv == -1)
234                                 goto error;
235                         rv = 1;
236                         if ((ms->flags & MAGIC_COMPRESS_TRANSP) != 0)
237                                 goto out;
238                         if (mime != MAGIC_MIME && mime != 0)
239                                 goto out;
240                         if ((file_printf(ms,
241                             mime ? " compressed-encoding=" : " (")) == -1)
242                                 goto error;
243                         if ((pb = file_push_buffer(ms)) == NULL)
244                                 goto error;
245                         /*
246                          * XXX: If file_buffer fails here, we overwrite
247                          * the compressed text. FIXME.
248                          */
249                         if (file_buffer(ms, -1, NULL, buf, nbytes) == -1)
250                                 goto error;
251                         if ((rbuf = file_pop_buffer(ms, pb)) != NULL) {
252                                 if (file_printf(ms, "%s", rbuf) == -1) {
253                                         free(rbuf);
254                                         goto error;
255                                 }
256                                 free(rbuf);
257                         }
258                         if (!mime && file_printf(ms, ")") == -1)
259                                 goto error;
260                         /*FALLTHROUGH*/
261                 case NODATA:
262                         break;
263                 default:
264                         abort();
265                         /*NOTREACHED*/
266                 error:
267                         rv = -1;
268                         break;
269                 }
270         }
271 out:
272         DPRINTF("rv = %d\n", rv);
273
274 #ifdef HAVE_SIGNAL_H
275         (void)signal(SIGPIPE, osigpipe);
276 #endif
277         free(newbuf);
278         ms->flags |= MAGIC_COMPRESS;
279         DPRINTF("Zmagic returns %d\n", rv);
280         return rv;
281 }
282 #endif
283 /*
284  * `safe' write for sockets and pipes.
285  */
286 private ssize_t
287 swrite(int fd, const void *buf, size_t n)
288 {
289         ssize_t rv;
290         size_t rn = n;
291
292         do
293                 switch (rv = write(fd, buf, n)) {
294                 case -1:
295                         if (errno == EINTR)
296                                 continue;
297                         return -1;
298                 default:
299                         n -= rv;
300                         buf = CAST(const char *, buf) + rv;
301                         break;
302                 }
303         while (n > 0);
304         return rn;
305 }
306
307
308 /*
309  * `safe' read for sockets and pipes.
310  */
311 protected ssize_t
312 sread(int fd, void *buf, size_t n, int canbepipe __attribute__((__unused__)))
313 {
314         ssize_t rv;
315 #ifdef FIONREAD
316         int t = 0;
317 #endif
318         size_t rn = n;
319
320         if (fd == STDIN_FILENO)
321                 goto nocheck;
322
323 #ifdef FIONREAD
324         if (canbepipe && (ioctl(fd, FIONREAD, &t) == -1 || t == 0)) {
325 #ifdef FD_ZERO
326                 ssize_t cnt;
327                 for (cnt = 0;; cnt++) {
328                         fd_set check;
329                         struct timeval tout = {0, 100 * 1000};
330                         int selrv;
331
332                         FD_ZERO(&check);
333                         FD_SET(fd, &check);
334
335                         /*
336                          * Avoid soft deadlock: do not read if there
337                          * is nothing to read from sockets and pipes.
338                          */
339                         selrv = select(fd + 1, &check, NULL, NULL, &tout);
340                         if (selrv == -1) {
341                                 if (errno == EINTR || errno == EAGAIN)
342                                         continue;
343                         } else if (selrv == 0 && cnt >= 5) {
344                                 return 0;
345                         } else
346                                 break;
347                 }
348 #endif
349                 (void)ioctl(fd, FIONREAD, &t);
350         }
351
352         if (t > 0 && (size_t)t < n) {
353                 n = t;
354                 rn = n;
355         }
356 #endif
357
358 nocheck:
359         do
360                 switch ((rv = read(fd, buf, n))) {
361                 case -1:
362                         if (errno == EINTR)
363                                 continue;
364                         return -1;
365                 case 0:
366                         return rn - n;
367                 default:
368                         n -= rv;
369                         buf = CAST(char *, CCAST(void *, buf)) + rv;
370                         break;
371                 }
372         while (n > 0);
373         return rn;
374 }
375
376 protected int
377 file_pipe2file(struct magic_set *ms, int fd, const void *startbuf,
378     size_t nbytes)
379 {
380         char buf[4096];
381         ssize_t r;
382         int tfd;
383
384         (void)strlcpy(buf, "/tmp/file.XXXXXX", sizeof buf);
385 #ifndef HAVE_MKSTEMP
386         {
387                 char *ptr = mktemp(buf);
388                 tfd = open(ptr, O_RDWR|O_TRUNC|O_EXCL|O_CREAT, 0600);
389                 r = errno;
390                 (void)unlink(ptr);
391                 errno = r;
392         }
393 #else
394         {
395                 int te;
396                 tfd = mkstemp(buf);
397                 te = errno;
398                 (void)unlink(buf);
399                 errno = te;
400         }
401 #endif
402         if (tfd == -1) {
403                 file_error(ms, errno,
404                     "cannot create temporary file for pipe copy");
405                 return -1;
406         }
407
408         if (swrite(tfd, startbuf, nbytes) != (ssize_t)nbytes)
409                 r = 1;
410         else {
411                 while ((r = sread(fd, buf, sizeof(buf), 1)) > 0)
412                         if (swrite(tfd, buf, (size_t)r) != r)
413                                 break;
414         }
415
416         switch (r) {
417         case -1:
418                 file_error(ms, errno, "error copying from pipe to temp file");
419                 return -1;
420         case 0:
421                 break;
422         default:
423                 file_error(ms, errno, "error while writing to temp file");
424                 return -1;
425         }
426
427         /*
428          * We duplicate the file descriptor, because fclose on a
429          * tmpfile will delete the file, but any open descriptors
430          * can still access the phantom inode.
431          */
432         if ((fd = dup2(tfd, fd)) == -1) {
433                 file_error(ms, errno, "could not dup descriptor for temp file");
434                 return -1;
435         }
436         (void)close(tfd);
437         if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) {
438                 file_badseek(ms);
439                 return -1;
440         }
441         return fd;
442 }
443 #if HAVE_FORK
444 #ifdef BUILTIN_DECOMPRESS
445
446 #define FHCRC           (1 << 1)
447 #define FEXTRA          (1 << 2)
448 #define FNAME           (1 << 3)
449 #define FCOMMENT        (1 << 4)
450
451
452 private int
453 uncompressgzipped(const unsigned char *old, unsigned char **newch,
454     size_t bytes_max, size_t *n)
455 {
456         unsigned char flg = old[3];
457         size_t data_start = 10;
458
459         if (flg & FEXTRA) {
460                 if (data_start + 1 >= *n)
461                         goto err;
462                 data_start += 2 + old[data_start] + old[data_start + 1] * 256;
463         }
464         if (flg & FNAME) {
465                 while(data_start < *n && old[data_start])
466                         data_start++;
467                 data_start++;
468         }
469         if (flg & FCOMMENT) {
470                 while(data_start < *n && old[data_start])
471                         data_start++;
472                 data_start++;
473         }
474         if (flg & FHCRC)
475                 data_start += 2;
476
477         if (data_start >= *n)
478                 goto err;
479
480         *n -= data_start;
481         old += data_start;
482         return uncompresszlib(old, newch, bytes_max, n, 0);
483 err:
484         return makeerror(newch, n, "File too short");
485 }
486
487 private int
488 uncompresszlib(const unsigned char *old, unsigned char **newch,
489     size_t bytes_max, size_t *n, int zlib)
490 {
491         int rc;
492         z_stream z;
493
494         if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL) 
495                 return makeerror(newch, n, "No buffer, %s", strerror(errno));
496
497         z.next_in = CCAST(Bytef *, old);
498         z.avail_in = CAST(uint32_t, *n);
499         z.next_out = *newch;
500         z.avail_out = bytes_max;
501         z.zalloc = Z_NULL;
502         z.zfree = Z_NULL;
503         z.opaque = Z_NULL;
504
505         /* LINTED bug in header macro */
506         rc = zlib ? inflateInit(&z) : inflateInit2(&z, -15);
507         if (rc != Z_OK)
508                 goto err;
509
510         rc = inflate(&z, Z_SYNC_FLUSH);
511         if (rc != Z_OK && rc != Z_STREAM_END)
512                 goto err;
513
514         *n = (size_t)z.total_out;
515         rc = inflateEnd(&z);
516         if (rc != Z_OK)
517                 goto err;
518         
519         /* let's keep the nul-terminate tradition */
520         (*newch)[*n] = '\0';
521
522         return OKDATA;
523 err:
524         strlcpy((char *)*newch, z.msg ? z.msg : zError(rc), bytes_max);
525         *n = strlen((char *)*newch);
526         return ERRDATA;
527 }
528 #endif
529
530 static int
531 makeerror(unsigned char **buf, size_t *len, const char *fmt, ...)
532 {
533         char *msg;
534         va_list ap;
535         int rv;
536
537         va_start(ap, fmt);
538         rv = vasprintf(&msg, fmt, ap);
539         va_end(ap);
540         if (rv < 0) {
541                 *buf = NULL;
542                 *len = 0;
543                 return NODATA;
544         }
545         *buf = (unsigned char *)msg;
546         *len = strlen(msg);
547         return ERRDATA;
548 }
549
550 static void
551 closefd(int *fd, size_t i)
552 {
553         if (fd[i] == -1)
554                 return;
555         (void) close(fd[i]);
556         fd[i] = -1;
557 }
558
559 static void
560 closep(int *fd)
561 {
562         size_t i;
563         for (i = 0; i < 2; i++)
564                 closefd(fd, i);
565 }
566
567 static void
568 copydesc(int i, int *fd)
569 {
570         int j = fd[i == STDIN_FILENO ? 0 : 1];
571         if (j == i)
572                 return;
573         if (dup2(j, i) == -1) {
574                 DPRINTF("dup(%d, %d) failed (%s)\n", j, i, strerror(errno));
575                 exit(1);
576         }
577         closep(fd);
578 }
579
580 static void
581 writechild(int fdp[3][2], const void *old, size_t n)
582 {
583         int status;
584
585         closefd(fdp[STDIN_FILENO], 0);
586         /* 
587          * fork again, to avoid blocking because both
588          * pipes filled
589          */
590         switch (fork()) {
591         case 0: /* child */
592                 closefd(fdp[STDOUT_FILENO], 0);
593                 if (swrite(fdp[STDIN_FILENO][1], old, n) != (ssize_t)n) {
594                         DPRINTF("Write failed (%s)\n", strerror(errno));
595                         exit(1);
596                 }
597                 exit(0);
598                 /*NOTREACHED*/
599
600         case -1:
601                 DPRINTF("Fork failed (%s)\n", strerror(errno));
602                 exit(1);
603                 /*NOTREACHED*/
604
605         default:  /* parent */
606                 if (wait(&status) == -1) {
607                         DPRINTF("Wait failed (%s)\n", strerror(errno));
608                         exit(1);
609                 }
610                 DPRINTF("Grandchild wait return %#x\n", status);
611         }
612         closefd(fdp[STDIN_FILENO], 1);
613 }
614
615 static ssize_t
616 filter_error(unsigned char *ubuf, ssize_t n)
617 {
618         char *p;
619         char *buf;
620
621         ubuf[n] = '\0';
622         buf = (char *)ubuf;
623         while (isspace((unsigned char)*buf))
624                 buf++;
625         DPRINTF("Filter error[[[%s]]]\n", buf);
626         if ((p = strchr((char *)buf, '\n')) != NULL)
627                 *p = '\0';
628         if ((p = strchr((char *)buf, ';')) != NULL)
629                 *p = '\0';
630         if ((p = strrchr((char *)buf, ':')) != NULL) {
631                 ++p;
632                 while (isspace((unsigned char)*p))
633                         p++;
634                 n = strlen(p);
635                 memmove(ubuf, p, n + 1);
636         }
637         DPRINTF("Filter error after[[[%s]]]\n", (char *)ubuf);
638         if (islower(*ubuf))
639                 *ubuf = toupper(*ubuf);
640         return n;
641 }
642
643 private const char *
644 methodname(size_t method)
645 {
646 #ifdef BUILTIN_DECOMPRESS
647         /* FIXME: This doesn't cope with bzip2 */
648         if (method == 2 || compr[method].maglen == 0)
649             return "zlib";
650 #endif
651         return compr[method].argv[0];
652 }
653
654 private int
655 uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old,
656     unsigned char **newch, size_t* n)
657 {
658         int fdp[3][2];
659         int status, rv;
660         size_t i;
661         ssize_t r;
662
663 #ifdef BUILTIN_DECOMPRESS
664         /* FIXME: This doesn't cope with bzip2 */
665         if (method == 2)
666                 return uncompressgzipped(old, newch, bytes_max, n);
667         if (compr[method].maglen == 0)
668                 return uncompresszlib(old, newch, bytes_max, n, 1);
669 #endif
670         (void)fflush(stdout);
671         (void)fflush(stderr);
672
673         for (i = 0; i < __arraycount(fdp); i++)
674                 fdp[i][0] = fdp[i][1] = -1;
675
676         if ((fd == -1 && pipe(fdp[STDIN_FILENO]) == -1) ||
677             pipe(fdp[STDOUT_FILENO]) == -1 || pipe(fdp[STDERR_FILENO]) == -1) {
678                 closep(fdp[STDIN_FILENO]);
679                 closep(fdp[STDOUT_FILENO]);
680                 return makeerror(newch, n, "Cannot create pipe, %s",
681                     strerror(errno));
682         }
683         switch (fork()) {
684         case 0: /* child */
685                 if (fd != -1) {
686                         fdp[STDIN_FILENO][0] = fd;
687                         (void) lseek(fd, (off_t)0, SEEK_SET);
688                 }
689                 
690                 for (i = 0; i < __arraycount(fdp); i++)
691                         copydesc(i, fdp[i]);
692
693                 (void)execvp(compr[method].argv[0],
694                     (char *const *)(intptr_t)compr[method].argv);
695                 dprintf(STDERR_FILENO, "exec `%s' failed, %s", 
696                     compr[method].argv[0], strerror(errno));
697                 exit(1);
698                 /*NOTREACHED*/
699         case -1:
700                 return makeerror(newch, n, "Cannot fork, %s",
701                     strerror(errno));
702
703         default: /* parent */
704                 for (i = 1; i < __arraycount(fdp); i++)
705                         closefd(fdp[i], 1);
706
707                 /* Write the buffer data to the child, if we don't have fd */
708                 if (fd == -1)
709                         writechild(fdp, old, *n);
710
711                 *newch = CAST(unsigned char *, malloc(bytes_max + 1));
712                 if (*newch == NULL) {
713                         rv = makeerror(newch, n, "No buffer, %s",
714                             strerror(errno));
715                         goto err;
716                 }
717                 rv = OKDATA;
718                 if ((r = sread(fdp[STDOUT_FILENO][0], *newch, bytes_max, 0)) > 0)
719                         break;
720                 DPRINTF("Read stdout failed %d (%s)\n", fdp[STDOUT_FILENO][0],
721                     r != -1 ? strerror(errno) : "no data");
722
723                 rv = ERRDATA;
724                 if (r == 0 &&
725                     (r = sread(fdp[STDERR_FILENO][0], *newch, bytes_max, 0)) > 0)
726                 {
727                         r = filter_error(*newch, r);
728                         break;
729                 }
730                 free(*newch);
731                 if  (r == 0)
732                         rv = makeerror(newch, n, "Read failed, %s",
733                             strerror(errno));
734                 else
735                         rv = makeerror(newch, n, "No data");
736                 goto err;
737         }
738
739         *n = r;
740         /* NUL terminate, as every buffer is handled here. */
741         (*newch)[*n] = '\0';
742 err:
743         closefd(fdp[STDIN_FILENO], 1);
744         closefd(fdp[STDOUT_FILENO], 0);
745         closefd(fdp[STDERR_FILENO], 0);
746         if (wait(&status) == -1) {
747                 free(*newch);
748                 rv = makeerror(newch, n, "Wait failed, %s", strerror(errno));
749                 DPRINTF("Child wait return %#x\n", status);
750         } else if (!WIFEXITED(status)) {
751                 DPRINTF("Child not exited (0x%x)\n", status);
752         } else if (WEXITSTATUS(status) != 0) {
753                 DPRINTF("Child exited (0x%d)\n", WEXITSTATUS(status));
754         }
755
756         closefd(fdp[STDIN_FILENO], 0);
757         DPRINTF("Returning %p n=%zu rv=%d\n", *newch, *n, rv);
758     
759         return rv;
760 }
761 #endif