1 /* $NetBSD: shf.c,v 1.13 2017/06/30 03:56:12 kamil Exp $ */ 2 3 /* 4 * Shell file I/O routines 5 */ 6 #include <sys/cdefs.h> 7 8 #ifndef lint 9 __RCSID("$NetBSD: shf.c,v 1.13 2017/06/30 03:56:12 kamil Exp $"); 10 #endif 11 12 #include <sys/stat.h> 13 14 #include "sh.h" 15 #include "ksh_limval.h" 16 17 18 /* flags to shf_emptybuf() */ 19 #define EB_READSW 0x01 /* about to switch to reading */ 20 #define EB_GROW 0x02 /* grow buffer if necessary (STRING+DYNAMIC) */ 21 22 /* 23 * Replacement stdio routines. Stdio is too flakey on too many machines 24 * to be useful when you have multiple processes using the same underlying 25 * file descriptors. 26 */ 27 28 static int shf_fillbuf ARGS((struct shf *shf)); 29 static int shf_emptybuf ARGS((struct shf *shf, int flags)); 30 31 /* Open a file. First three args are for open(), last arg is flags for 32 * this package. Returns NULL if file could not be opened, or if a dup 33 * fails. 34 */ 35 struct shf * 36 shf_open(name, oflags, mode, sflags) 37 const char *name; 38 int oflags; 39 int mode; 40 int sflags; 41 { 42 struct shf *shf; 43 int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE; 44 int fd; 45 46 /* Done before open so if alloca fails, fd won't be lost. */ 47 shf = (struct shf *) alloc(sizeof(struct shf) + bsize, ATEMP); 48 shf->areap = ATEMP; 49 shf->buf = (unsigned char *) &shf[1]; 50 shf->bsize = bsize; 51 shf->flags = SHF_ALLOCS; 52 /* Rest filled in by reopen. */ 53 54 fd = open(name, oflags, mode); 55 if (fd < 0) { 56 afree(shf, shf->areap); 57 return NULL; 58 } 59 if ((sflags & SHF_MAPHI) && fd < FDBASE) { 60 int nfd; 61 62 nfd = ksh_dupbase(fd, FDBASE); 63 close(fd); 64 if (nfd < 0) { 65 afree(shf, shf->areap); 66 return NULL; 67 } 68 fd = nfd; 69 } 70 sflags &= ~SHF_ACCMODE; 71 sflags |= (oflags & O_ACCMODE) == O_RDONLY ? SHF_RD 72 : ((oflags & O_ACCMODE) == O_WRONLY ? SHF_WR 73 : SHF_RDWR); 74 75 return shf_reopen(fd, sflags, shf); 76 } 77 78 /* Set up the shf structure for a file descriptor. Doesn't fail. */ 79 struct shf * 80 shf_fdopen(fd, sflags, shf) 81 int fd; 82 int sflags; 83 struct shf *shf; 84 { 85 int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE; 86 87 /* use fcntl() to figure out correct read/write flags */ 88 if (sflags & SHF_GETFL) { 89 int flags = fcntl(fd, F_GETFL, 0); 90 91 if (flags < 0) 92 /* will get an error on first read/write */ 93 sflags |= SHF_RDWR; 94 else 95 switch (flags & O_ACCMODE) { 96 case O_RDONLY: sflags |= SHF_RD; break; 97 case O_WRONLY: sflags |= SHF_WR; break; 98 case O_RDWR: sflags |= SHF_RDWR; break; 99 } 100 } 101 102 if (!(sflags & (SHF_RD | SHF_WR))) 103 internal_errorf(1, "shf_fdopen: missing read/write"); 104 105 if (shf) { 106 if (bsize) { 107 shf->buf = (unsigned char *) alloc(bsize, ATEMP); 108 sflags |= SHF_ALLOCB; 109 } else 110 shf->buf = (unsigned char *) 0; 111 } else { 112 shf = (struct shf *) alloc(sizeof(struct shf) + bsize, ATEMP); 113 shf->buf = (unsigned char *) &shf[1]; 114 sflags |= SHF_ALLOCS; 115 } 116 shf->areap = ATEMP; 117 shf->fd = fd; 118 shf->rp = shf->wp = shf->buf; 119 shf->rnleft = 0; 120 shf->rbsize = bsize; 121 shf->wnleft = 0; /* force call to shf_emptybuf() */ 122 shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize; 123 shf->flags = sflags; 124 shf->errno_ = 0; 125 shf->bsize = bsize; 126 if (sflags & SHF_CLEXEC) 127 fd_clexec(fd); 128 return shf; 129 } 130 131 /* Set up an existing shf (and buffer) to use the given fd */ 132 struct shf * 133 shf_reopen(fd, sflags, shf) 134 int fd; 135 int sflags; 136 struct shf *shf; 137 { 138 int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE; 139 140 /* use fcntl() to figure out correct read/write flags */ 141 if (sflags & SHF_GETFL) { 142 int flags = fcntl(fd, F_GETFL, 0); 143 144 if (flags < 0) 145 /* will get an error on first read/write */ 146 sflags |= SHF_RDWR; 147 else 148 switch (flags & O_ACCMODE) { 149 case O_RDONLY: sflags |= SHF_RD; break; 150 case O_WRONLY: sflags |= SHF_WR; break; 151 case O_RDWR: sflags |= SHF_RDWR; break; 152 } 153 } 154 155 if (!(sflags & (SHF_RD | SHF_WR))) 156 internal_errorf(1, "shf_reopen: missing read/write"); 157 if (!shf || !shf->buf || shf->bsize < bsize) 158 internal_errorf(1, "shf_reopen: bad shf/buf/bsize"); 159 160 /* assumes shf->buf and shf->bsize already set up */ 161 shf->fd = fd; 162 shf->rp = shf->wp = shf->buf; 163 shf->rnleft = 0; 164 shf->rbsize = bsize; 165 shf->wnleft = 0; /* force call to shf_emptybuf() */ 166 shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize; 167 shf->flags = (shf->flags & (SHF_ALLOCS | SHF_ALLOCB)) | sflags; 168 shf->errno_ = 0; 169 if (sflags & SHF_CLEXEC) 170 fd_clexec(fd); 171 return shf; 172 } 173 174 /* Open a string for reading or writing. If reading, bsize is the number 175 * of bytes that can be read. If writing, bsize is the maximum number of 176 * bytes that can be written. If shf is not null, it is filled in and 177 * returned, if it is null, shf is allocated. If writing and buf is null 178 * and SHF_DYNAMIC is set, the buffer is allocated (if bsize > 0, it is 179 * used for the initial size). Doesn't fail. 180 * When writing, a byte is reserved for a trailing null - see shf_sclose(). 181 */ 182 struct shf * 183 shf_sopen(buf, bsize, sflags, shf) 184 char *buf; 185 int bsize; 186 int sflags; 187 struct shf *shf; 188 { 189 /* can't have a read+write string */ 190 if (!(sflags & (SHF_RD | SHF_WR)) 191 || (sflags & (SHF_RD | SHF_WR)) == (SHF_RD | SHF_WR)) 192 internal_errorf(1, "shf_sopen: flags 0x%x", sflags); 193 194 if (!shf) { 195 shf = (struct shf *) alloc(sizeof(struct shf), ATEMP); 196 sflags |= SHF_ALLOCS; 197 } 198 shf->areap = ATEMP; 199 if (!buf && (sflags & SHF_WR) && (sflags & SHF_DYNAMIC)) { 200 if (bsize <= 0) 201 bsize = 64; 202 sflags |= SHF_ALLOCB; 203 buf = alloc(bsize, shf->areap); 204 } 205 shf->fd = -1; 206 shf->buf = shf->rp = shf->wp = (unsigned char *) buf; 207 shf->rnleft = bsize; 208 shf->rbsize = bsize; 209 shf->wnleft = bsize - 1; /* space for a '\0' */ 210 shf->wbsize = bsize; 211 shf->flags = sflags | SHF_STRING; 212 shf->errno_ = 0; 213 shf->bsize = bsize; 214 215 return shf; 216 } 217 218 /* Flush and close file descriptor, free the shf structure */ 219 int 220 shf_close(shf) 221 struct shf *shf; 222 { 223 int ret = 0; 224 225 if (shf->fd >= 0) { 226 ret = shf_flush(shf); 227 if (close(shf->fd) < 0) 228 ret = EOF; 229 } 230 if (shf->flags & SHF_ALLOCS) 231 afree(shf, shf->areap); 232 else if (shf->flags & SHF_ALLOCB) 233 afree(shf->buf, shf->areap); 234 235 return ret; 236 } 237 238 /* Flush and close file descriptor, don't free file structure */ 239 int 240 shf_fdclose(shf) 241 struct shf *shf; 242 { 243 int ret = 0; 244 245 if (shf->fd >= 0) { 246 ret = shf_flush(shf); 247 if (close(shf->fd) < 0) 248 ret = EOF; 249 shf->rnleft = 0; 250 shf->rp = shf->buf; 251 shf->wnleft = 0; 252 shf->fd = -1; 253 } 254 255 return ret; 256 } 257 258 /* Close a string - if it was opened for writing, it is null terminated; 259 * returns a pointer to the string and frees shf if it was allocated 260 * (does not free string if it was allocated). 261 */ 262 char * 263 shf_sclose(shf) 264 struct shf *shf; 265 { 266 unsigned char *s = shf->buf; 267 268 /* null terminate */ 269 if (shf->flags & SHF_WR) { 270 shf->wnleft++; 271 shf_putc('\0', shf); 272 } 273 if (shf->flags & SHF_ALLOCS) 274 afree(shf, shf->areap); 275 return (char *) s; 276 } 277 278 /* Flush and free file structure, don't close file descriptor */ 279 int 280 shf_finish(shf) 281 struct shf *shf; 282 { 283 int ret = 0; 284 285 if (shf->fd >= 0) 286 ret = shf_flush(shf); 287 if (shf->flags & SHF_ALLOCS) 288 afree(shf, shf->areap); 289 else if (shf->flags & SHF_ALLOCB) 290 afree(shf->buf, shf->areap); 291 292 return ret; 293 } 294 295 /* Un-read what has been read but not examined, or write what has been 296 * buffered. Returns 0 for success, EOF for (write) error. 297 */ 298 int 299 shf_flush(shf) 300 struct shf *shf; 301 { 302 if (shf->flags & SHF_STRING) 303 return (shf->flags & SHF_WR) ? EOF : 0; 304 305 if (shf->fd < 0) 306 internal_errorf(1, "shf_flush: no fd"); 307 308 if (shf->flags & SHF_ERROR) { 309 errno = shf->errno_; 310 return EOF; 311 } 312 313 if (shf->flags & SHF_READING) { 314 shf->flags &= ~(SHF_EOF | SHF_READING); 315 if (shf->rnleft > 0) { 316 lseek(shf->fd, (off_t) -shf->rnleft, 1); 317 shf->rnleft = 0; 318 shf->rp = shf->buf; 319 } 320 return 0; 321 } else if (shf->flags & SHF_WRITING) 322 return shf_emptybuf(shf, 0); 323 324 return 0; 325 } 326 327 /* Write out any buffered data. If currently reading, flushes the read 328 * buffer. Returns 0 for success, EOF for (write) error. 329 */ 330 static int 331 shf_emptybuf(shf, flags) 332 struct shf *shf; 333 int flags; 334 { 335 int ret = 0; 336 337 if (!(shf->flags & SHF_STRING) && shf->fd < 0) 338 internal_errorf(1, "shf_emptybuf: no fd"); 339 340 if (shf->flags & SHF_ERROR) { 341 errno = shf->errno_; 342 return EOF; 343 } 344 345 if (shf->flags & SHF_READING) { 346 if (flags & EB_READSW) /* doesn't happen */ 347 return 0; 348 ret = shf_flush(shf); 349 shf->flags &= ~SHF_READING; 350 } 351 if (shf->flags & SHF_STRING) { 352 unsigned char *nbuf; 353 354 /* Note that we assume SHF_ALLOCS is not set if SHF_ALLOCB 355 * is set... (changing the shf pointer could cause problems) 356 */ 357 if (!(flags & EB_GROW) || !(shf->flags & SHF_DYNAMIC) 358 || !(shf->flags & SHF_ALLOCB)) 359 return EOF; 360 /* allocate more space for buffer */ 361 nbuf = (unsigned char *) aresize(shf->buf, shf->wbsize * 2, 362 shf->areap); 363 shf->rp = nbuf + (shf->rp - shf->buf); 364 shf->wp = nbuf + (shf->wp - shf->buf); 365 shf->rbsize += shf->wbsize; 366 shf->wnleft += shf->wbsize; 367 shf->wbsize *= 2; 368 shf->buf = nbuf; 369 } else { 370 if (shf->flags & SHF_WRITING) { 371 int ntowrite = shf->wp - shf->buf; 372 unsigned char *buf = shf->buf; 373 int n; 374 375 while (ntowrite > 0) { 376 n = write(shf->fd, buf, ntowrite); 377 if (n < 0) { 378 if (errno == EINTR 379 && !(shf->flags & SHF_INTERRUPT)) 380 continue; 381 shf->flags |= SHF_ERROR; 382 shf->errno_ = errno; 383 shf->wnleft = 0; 384 if (buf != shf->buf) { 385 /* allow a second flush 386 * to work */ 387 memmove(shf->buf, buf, 388 ntowrite); 389 shf->wp = shf->buf + ntowrite; 390 } 391 return EOF; 392 } 393 buf += n; 394 ntowrite -= n; 395 } 396 if (flags & EB_READSW) { 397 shf->wp = shf->buf; 398 shf->wnleft = 0; 399 shf->flags &= ~SHF_WRITING; 400 return 0; 401 } 402 } 403 shf->wp = shf->buf; 404 shf->wnleft = shf->wbsize; 405 } 406 shf->flags |= SHF_WRITING; 407 408 return ret; 409 } 410 411 /* Fill up a read buffer. Returns EOF for a read error, 0 otherwise. */ 412 static int 413 shf_fillbuf(shf) 414 struct shf *shf; 415 { 416 if (shf->flags & SHF_STRING) 417 return 0; 418 419 if (shf->fd < 0) 420 internal_errorf(1, "shf_fillbuf: no fd"); 421 422 if (shf->flags & (SHF_EOF | SHF_ERROR)) { 423 if (shf->flags & SHF_ERROR) 424 errno = shf->errno_; 425 return EOF; 426 } 427 428 if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF) 429 return EOF; 430 431 shf->flags |= SHF_READING; 432 433 shf->rp = shf->buf; 434 while (1) { 435 shf->rnleft = blocking_read(shf->fd, (char *) shf->buf, 436 shf->rbsize); 437 if (shf->rnleft < 0 && errno == EINTR 438 && !(shf->flags & SHF_INTERRUPT)) 439 continue; 440 break; 441 } 442 if (shf->rnleft <= 0) { 443 if (shf->rnleft < 0) { 444 shf->flags |= SHF_ERROR; 445 shf->errno_ = errno; 446 shf->rnleft = 0; 447 shf->rp = shf->buf; 448 return EOF; 449 } 450 shf->flags |= SHF_EOF; 451 } 452 return 0; 453 } 454 455 /* Seek to a new position in the file. If writing, flushes the buffer 456 * first. If reading, optimizes small relative seeks that stay inside the 457 * buffer. Returns 0 for success, EOF otherwise. 458 */ 459 int 460 shf_seek(shf, where, from) 461 struct shf *shf; 462 off_t where; 463 int from; 464 { 465 if (shf->fd < 0) { 466 errno = EINVAL; 467 return EOF; 468 } 469 470 if (shf->flags & SHF_ERROR) { 471 errno = shf->errno_; 472 return EOF; 473 } 474 475 if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF) 476 return EOF; 477 478 if (shf->flags & SHF_READING) { 479 if (from == SEEK_CUR && 480 (where < 0 ? 481 -where >= shf->rbsize - shf->rnleft : 482 where < shf->rnleft)) { 483 shf->rnleft -= where; 484 shf->rp += where; 485 return 0; 486 } 487 shf->rnleft = 0; 488 shf->rp = shf->buf; 489 } 490 491 shf->flags &= ~(SHF_EOF | SHF_READING | SHF_WRITING); 492 493 if (lseek(shf->fd, where, from) < 0) { 494 shf->errno_ = errno; 495 shf->flags |= SHF_ERROR; 496 return EOF; 497 } 498 499 return 0; 500 } 501 502 503 /* Read a buffer from shf. Returns the number of bytes read into buf, 504 * if no bytes were read, returns 0 if end of file was seen, EOF if 505 * a read error occurred. 506 */ 507 int 508 shf_read(buf, bsize, shf) 509 char *buf; 510 int bsize; 511 struct shf *shf; 512 { 513 int orig_bsize = bsize; 514 int ncopy; 515 516 if (!(shf->flags & SHF_RD)) 517 internal_errorf(1, "shf_read: flags %x", shf->flags); 518 519 if (bsize <= 0) 520 internal_errorf(1, "shf_read: bsize %d", bsize); 521 522 while (bsize > 0) { 523 if (shf->rnleft == 0 524 && (shf_fillbuf(shf) == EOF || shf->rnleft == 0)) 525 break; 526 ncopy = shf->rnleft; 527 if (ncopy > bsize) 528 ncopy = bsize; 529 memcpy(buf, shf->rp, ncopy); 530 buf += ncopy; 531 bsize -= ncopy; 532 shf->rp += ncopy; 533 shf->rnleft -= ncopy; 534 } 535 /* Note: fread(3S) returns 0 for errors - this doesn't */ 536 return orig_bsize == bsize ? (shf_error(shf) ? EOF : 0) 537 : orig_bsize - bsize; 538 } 539 540 /* Read up to a newline or EOF. The newline is put in buf; buf is always 541 * null terminated. Returns NULL on read error or if nothing was read before 542 * end of file, returns a pointer to the null byte in buf otherwise. 543 */ 544 char * 545 shf_getse(buf, bsize, shf) 546 char *buf; 547 int bsize; 548 struct shf *shf; 549 { 550 unsigned char *end; 551 int ncopy; 552 char *orig_buf = buf; 553 554 if (!(shf->flags & SHF_RD)) 555 internal_errorf(1, "shf_getse: flags %x", shf->flags); 556 557 if (bsize <= 0) 558 return (char *) 0; 559 560 --bsize; /* save room for null */ 561 do { 562 if (shf->rnleft == 0) { 563 if (shf_fillbuf(shf) == EOF) 564 return NULL; 565 if (shf->rnleft == 0) { 566 *buf = '\0'; 567 return buf == orig_buf ? NULL : buf; 568 } 569 } 570 end = (unsigned char *) memchr((char *) shf->rp, '\n', 571 shf->rnleft); 572 ncopy = end ? end - shf->rp + 1 : shf->rnleft; 573 if (ncopy > bsize) 574 ncopy = bsize; 575 memcpy(buf, (char *) shf->rp, ncopy); 576 shf->rp += ncopy; 577 shf->rnleft -= ncopy; 578 buf += ncopy; 579 bsize -= ncopy; 580 581 } while (!end && bsize); 582 *buf = '\0'; 583 return buf; 584 } 585 586 /* Returns the char read. Returns EOF for error and end of file. */ 587 int 588 shf_getchar(shf) 589 struct shf *shf; 590 { 591 if (!(shf->flags & SHF_RD)) 592 internal_errorf(1, "shf_getchar: flags %x", shf->flags); 593 594 if (shf->rnleft == 0 && (shf_fillbuf(shf) == EOF || shf->rnleft == 0)) 595 return EOF; 596 --shf->rnleft; 597 return *shf->rp++; 598 } 599 600 /* Put a character back in the input stream. Returns the character if 601 * successful, EOF if there is no room. 602 */ 603 int 604 shf_ungetc(c, shf) 605 int c; 606 struct shf *shf; 607 { 608 if (!(shf->flags & SHF_RD)) 609 internal_errorf(1, "shf_ungetc: flags %x", shf->flags); 610 611 if ((shf->flags & SHF_ERROR) || c == EOF 612 || (shf->rp == shf->buf && shf->rnleft)) 613 return EOF; 614 615 if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF) 616 return EOF; 617 618 if (shf->rp == shf->buf) 619 shf->rp = shf->buf + shf->rbsize; 620 if (shf->flags & SHF_STRING) { 621 /* Can unget what was read, but not something different - we 622 * don't want to modify a string. 623 */ 624 if (shf->rp[-1] != c) 625 return EOF; 626 shf->flags &= ~SHF_EOF; 627 shf->rp--; 628 shf->rnleft++; 629 return c; 630 } 631 shf->flags &= ~SHF_EOF; 632 *--(shf->rp) = c; 633 shf->rnleft++; 634 return c; 635 } 636 637 /* Write a character. Returns the character if successful, EOF if 638 * the char could not be written. 639 */ 640 int 641 shf_putchar(c, shf) 642 int c; 643 struct shf *shf; 644 { 645 if (!(shf->flags & SHF_WR)) 646 internal_errorf(1, "shf_putchar: flags %x", shf->flags); 647 648 if (c == EOF) 649 return EOF; 650 651 if (shf->flags & SHF_UNBUF) { 652 char cc = c; 653 int n; 654 655 if (shf->fd < 0) 656 internal_errorf(1, "shf_putchar: no fd"); 657 if (shf->flags & SHF_ERROR) { 658 errno = shf->errno_; 659 return EOF; 660 } 661 while ((n = write(shf->fd, &cc, 1)) != 1) 662 if (n < 0) { 663 if (errno == EINTR 664 && !(shf->flags & SHF_INTERRUPT)) 665 continue; 666 shf->flags |= SHF_ERROR; 667 shf->errno_ = errno; 668 return EOF; 669 } 670 } else { 671 /* Flush deals with strings and sticky errors */ 672 if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == EOF) 673 return EOF; 674 shf->wnleft--; 675 *shf->wp++ = c; 676 } 677 678 return c; 679 } 680 681 /* Write a string. Returns the length of the string if successful, EOF if 682 * the string could not be written. 683 */ 684 int 685 shf_puts(s, shf) 686 const char *s; 687 struct shf *shf; 688 { 689 if (!s) 690 return EOF; 691 692 return shf_write(s, strlen(s), shf); 693 } 694 695 /* Write a buffer. Returns nbytes if successful, EOF if there is an error. */ 696 int 697 shf_write(buf, nbytes, shf) 698 const char *buf; 699 int nbytes; 700 struct shf *shf; 701 { 702 int orig_nbytes = nbytes; 703 int n; 704 int ncopy; 705 706 if (!(shf->flags & SHF_WR)) 707 internal_errorf(1, "shf_write: flags %x", shf->flags); 708 709 if (nbytes < 0) 710 internal_errorf(1, "shf_write: nbytes %d", nbytes); 711 712 /* Don't buffer if buffer is empty and we're writting a large amount. */ 713 if ((ncopy = shf->wnleft) 714 && (shf->wp != shf->buf || nbytes < shf->wnleft)) 715 { 716 if (ncopy > nbytes) 717 ncopy = nbytes; 718 memcpy(shf->wp, buf, ncopy); 719 nbytes -= ncopy; 720 buf += ncopy; 721 shf->wp += ncopy; 722 shf->wnleft -= ncopy; 723 } 724 if (nbytes > 0) { 725 /* Flush deals with strings and sticky errors */ 726 if (shf_emptybuf(shf, EB_GROW) == EOF) 727 return EOF; 728 if (nbytes > shf->wbsize) { 729 ncopy = nbytes; 730 if (shf->wbsize) 731 ncopy -= nbytes % shf->wbsize; 732 nbytes -= ncopy; 733 while (ncopy > 0) { 734 n = write(shf->fd, buf, ncopy); 735 if (n < 0) { 736 if (errno == EINTR 737 && !(shf->flags & SHF_INTERRUPT)) 738 continue; 739 shf->flags |= SHF_ERROR; 740 shf->errno_ = errno; 741 shf->wnleft = 0; 742 /* Note: fwrite(3S) returns 0 for 743 * errors - this doesn't */ 744 return EOF; 745 } 746 buf += n; 747 ncopy -= n; 748 } 749 } 750 if (nbytes > 0) { 751 memcpy(shf->wp, buf, nbytes); 752 shf->wp += nbytes; 753 shf->wnleft -= nbytes; 754 } 755 } 756 757 return orig_nbytes; 758 } 759 760 int 761 shf_fprintf(struct shf *shf, const char *fmt, ...) 762 { 763 va_list args; 764 int n; 765 766 va_start(args, fmt); 767 n = shf_vfprintf(shf, fmt, args); 768 va_end(args); 769 770 return n; 771 } 772 773 int 774 shf_snprintf(char *buf, int bsize, const char *fmt, ...) 775 { 776 struct shf shf; 777 va_list args; 778 int n; 779 780 if (!buf || bsize <= 0) 781 internal_errorf(1, "shf_snprintf: buf %lx, bsize %d", 782 (long) buf, bsize); 783 784 shf_sopen(buf, bsize, SHF_WR, &shf); 785 va_start(args, fmt); 786 n = shf_vfprintf(&shf, fmt, args); 787 va_end(args); 788 shf_sclose(&shf); /* null terminates */ 789 return n; 790 } 791 792 char * 793 shf_smprintf(const char *fmt, ...) 794 { 795 struct shf shf; 796 va_list args; 797 798 shf_sopen((char *) 0, 0, SHF_WR|SHF_DYNAMIC, &shf); 799 va_start(args, fmt); 800 shf_vfprintf(&shf, fmt, args); 801 va_end(args); 802 return shf_sclose(&shf); /* null terminates */ 803 } 804 805 #undef FP /* if you want floating point stuff */ 806 807 #define BUF_SIZE 128 808 #define FPBUF_SIZE (DMAXEXP+16)/* this must be > 809 * MAX(DMAXEXP, log10(pow(2, DSIGNIF))) 810 * + ceil(log10(DMAXEXP)) + 8 (I think). 811 * Since this is hard to express as a 812 * constant, just use a large buffer. 813 */ 814 815 /* 816 * What kinda of machine we on? Hopefully the C compiler will optimize 817 * this out... 818 * 819 * For shorts, we want sign extend for %d but not for %[oxu] - on 16 bit 820 * machines it don't matter. Assumes C compiler has converted shorts to 821 * ints before pushing them. 822 */ 823 #define POP_INT(f, s, a) (((f) & FL_LONG) ? \ 824 va_arg((a), unsigned long) \ 825 : \ 826 (sizeof(int) < sizeof(long) ? \ 827 ((s) ? \ 828 (long) va_arg((a), int) \ 829 : \ 830 va_arg((a), unsigned)) \ 831 : \ 832 va_arg((a), unsigned))) 833 834 #define ABIGNUM 32000 /* big numer that will fit in a short */ 835 #define LOG2_10 3.321928094887362347870319429 /* log base 2 of 10 */ 836 837 #define FL_HASH 0x001 /* `#' seen */ 838 #define FL_PLUS 0x002 /* `+' seen */ 839 #define FL_RIGHT 0x004 /* `-' seen */ 840 #define FL_BLANK 0x008 /* ` ' seen */ 841 #define FL_SHORT 0x010 /* `h' seen */ 842 #define FL_LONG 0x020 /* `l' seen */ 843 #define FL_ZERO 0x040 /* `0' seen */ 844 #define FL_DOT 0x080 /* '.' seen */ 845 #define FL_UPPER 0x100 /* format character was uppercase */ 846 #define FL_NUMBER 0x200 /* a number was formated %[douxefg] */ 847 848 849 #ifdef FP 850 #include <math.h> 851 852 static double 853 my_ceil(d) 854 double d; 855 { 856 double i; 857 858 return d - modf(d, &i) + (d < 0 ? -1 : 1); 859 } 860 #endif /* FP */ 861 862 int 863 shf_vfprintf(shf, fmt, args) 864 struct shf *shf; 865 const char *fmt; 866 va_list args; 867 { 868 char c, *s; 869 int UNINITIALIZED(tmp); 870 int field, precision; 871 int len; 872 int flags; 873 unsigned long lnum; 874 /* %#o produces the longest output */ 875 char numbuf[(BITS(long) + 2) / 3 + 1]; 876 /* this stuff for dealing with the buffer */ 877 int nwritten = 0; 878 static char nulls[] = "(null %s)"; 879 #ifdef FP 880 /* should be in <math.h> 881 * extern double frexp(); 882 */ 883 extern char *ecvt(); 884 885 double fpnum; 886 int expo, decpt; 887 char style; 888 char fpbuf[FPBUF_SIZE]; 889 #endif /* FP */ 890 891 if (!fmt) 892 return 0; 893 894 while ((c = *fmt++)) { 895 if (c != '%') { 896 shf_putc(c, shf); 897 nwritten++; 898 continue; 899 } 900 /* 901 * This will accept flags/fields in any order - not 902 * just the order specified in printf(3), but this is 903 * the way _doprnt() seems to work (on bsd and sysV). 904 * The only restriction is that the format character must 905 * come last :-). 906 */ 907 flags = field = precision = 0; 908 for ( ; (c = *fmt++) ; ) { 909 switch (c) { 910 case '#': 911 flags |= FL_HASH; 912 continue; 913 914 case '+': 915 flags |= FL_PLUS; 916 continue; 917 918 case '-': 919 flags |= FL_RIGHT; 920 continue; 921 922 case ' ': 923 flags |= FL_BLANK; 924 continue; 925 926 case '0': 927 if (!(flags & FL_DOT)) 928 flags |= FL_ZERO; 929 continue; 930 931 case '.': 932 flags |= FL_DOT; 933 precision = 0; 934 continue; 935 936 case '*': 937 tmp = va_arg(args, int); 938 if (flags & FL_DOT) 939 precision = tmp; 940 else if ((field = tmp) < 0) { 941 field = -field; 942 flags |= FL_RIGHT; 943 } 944 continue; 945 946 case 'l': 947 flags |= FL_LONG; 948 continue; 949 950 case 'h': 951 flags |= FL_SHORT; 952 continue; 953 } 954 if (digit(c)) { 955 tmp = c - '0'; 956 while (c = *fmt++, digit(c)) 957 tmp = tmp * 10 + c - '0'; 958 --fmt; 959 if (tmp < 0) /* overflow? */ 960 tmp = 0; 961 if (flags & FL_DOT) 962 precision = tmp; 963 else 964 field = tmp; 965 continue; 966 } 967 break; 968 } 969 970 if (precision < 0) 971 precision = 0; 972 973 if (!c) /* nasty format */ 974 break; 975 976 if (c >= 'A' && c <= 'Z') { 977 flags |= FL_UPPER; 978 c = c - 'A' + 'a'; 979 } 980 981 switch (c) { 982 case 'p': /* pointer */ 983 flags &= ~(FL_LONG | FL_SHORT); 984 if (sizeof(char *) > sizeof(int)) 985 flags |= FL_LONG; /* hope it fits.. */ 986 /* aaahhh... */ 987 case 'd': 988 case 'i': 989 case 'o': 990 case 'u': 991 case 'x': 992 flags |= FL_NUMBER; 993 s = &numbuf[sizeof(numbuf)]; 994 lnum = POP_INT(flags, c == 'd', args); 995 switch (c) { 996 case 'd': 997 case 'i': 998 if (0 > (long) lnum) 999 lnum = - (long) lnum, tmp = 1; 1000 else 1001 tmp = 0; 1002 /* aaahhhh..... */ 1003 1004 case 'u': 1005 do { 1006 *--s = lnum % 10 + '0'; 1007 lnum /= 10; 1008 } while (lnum); 1009 1010 if (c != 'u') { 1011 if (tmp) 1012 *--s = '-'; 1013 else if (flags & FL_PLUS) 1014 *--s = '+'; 1015 else if (flags & FL_BLANK) 1016 *--s = ' '; 1017 } 1018 break; 1019 1020 case 'o': 1021 do { 1022 *--s = (lnum & 0x7) + '0'; 1023 lnum >>= 3; 1024 } while (lnum); 1025 1026 if ((flags & FL_HASH) && *s != '0') 1027 *--s = '0'; 1028 break; 1029 1030 case 'p': 1031 case 'x': 1032 { 1033 const char *digits = (flags & FL_UPPER) ? 1034 "0123456789ABCDEF" 1035 : "0123456789abcdef"; 1036 do { 1037 *--s = digits[lnum & 0xf]; 1038 lnum >>= 4; 1039 } while (lnum); 1040 1041 if (flags & FL_HASH) { 1042 *--s = (flags & FL_UPPER) ? 'X' : 'x'; 1043 *--s = '0'; 1044 } 1045 } 1046 } 1047 len = &numbuf[sizeof(numbuf)] - s; 1048 if (flags & FL_DOT) { 1049 if (precision > len) { 1050 field = precision; 1051 flags |= FL_ZERO; 1052 } else 1053 precision = len; /* no loss */ 1054 } 1055 break; 1056 1057 #ifdef FP 1058 case 'e': 1059 case 'g': 1060 case 'f': 1061 { 1062 char *p; 1063 1064 /* 1065 * This could probably be done better, 1066 * but it seems to work. Note that gcvt() 1067 * is not used, as you cannot tell it to 1068 * not strip the zeros. 1069 */ 1070 flags |= FL_NUMBER; 1071 if (!(flags & FL_DOT)) 1072 precision = 6; /* default */ 1073 /* 1074 * Assumes doubles are pushed on 1075 * the stack. If this is not so, then 1076 * FL_LONG/FL_SHORT should be checked. 1077 */ 1078 fpnum = va_arg(args, double); 1079 s = fpbuf; 1080 style = c; 1081 /* 1082 * This is the same as 1083 * expo = ceil(log10(fpnum)) 1084 * but doesn't need -lm. This is an 1085 * approximation as expo is rounded up. 1086 */ 1087 (void) frexp(fpnum, &expo); 1088 expo = my_ceil(expo / LOG2_10); 1089 1090 if (expo < 0) 1091 expo = 0; 1092 1093 p = ecvt(fpnum, precision + 1 + expo, 1094 &decpt, &tmp); 1095 if (c == 'g') { 1096 if (decpt < -4 || decpt > precision) 1097 style = 'e'; 1098 else 1099 style = 'f'; 1100 if (decpt > 0 && (precision -= decpt) < 0) 1101 precision = 0; 1102 } 1103 if (tmp) 1104 *s++ = '-'; 1105 else if (flags & FL_PLUS) 1106 *s++ = '+'; 1107 else if (flags & FL_BLANK) 1108 *s++ = ' '; 1109 1110 if (style == 'e') 1111 *s++ = *p++; 1112 else { 1113 if (decpt > 0) { 1114 /* Overflow check - should 1115 * never have this problem. 1116 */ 1117 if (decpt > 1118 &fpbuf[sizeof(fpbuf)] 1119 - s - 8) 1120 decpt = 1121 &fpbuf[sizeof(fpbuf)] 1122 - s - 8; 1123 (void) memcpy(s, p, decpt); 1124 s += decpt; 1125 p += decpt; 1126 } else 1127 *s++ = '0'; 1128 } 1129 1130 /* print the fraction? */ 1131 if (precision > 0) { 1132 *s++ = '.'; 1133 /* Overflow check - should 1134 * never have this problem. 1135 */ 1136 if (precision > &fpbuf[sizeof(fpbuf)] 1137 - s - 7) 1138 precision = 1139 &fpbuf[sizeof(fpbuf)] 1140 - s - 7; 1141 for (tmp = decpt; tmp++ < 0 && 1142 precision > 0 ; precision--) 1143 *s++ = '0'; 1144 tmp = strlen(p); 1145 if (precision > tmp) 1146 precision = tmp; 1147 /* Overflow check - should 1148 * never have this problem. 1149 */ 1150 if (precision > &fpbuf[sizeof(fpbuf)] 1151 - s - 7) 1152 precision = 1153 &fpbuf[sizeof(fpbuf)] 1154 - s - 7; 1155 (void) memcpy(s, p, precision); 1156 s += precision; 1157 /* 1158 * `g' format strips trailing 1159 * zeros after the decimal. 1160 */ 1161 if (c == 'g' && !(flags & FL_HASH)) { 1162 while (*--s == '0') 1163 ; 1164 if (*s != '.') 1165 s++; 1166 } 1167 } else if (flags & FL_HASH) 1168 *s++ = '.'; 1169 1170 if (style == 'e') { 1171 *s++ = (flags & FL_UPPER) ? 'E' : 'e'; 1172 if (--decpt >= 0) 1173 *s++ = '+'; 1174 else { 1175 *s++ = '-'; 1176 decpt = -decpt; 1177 } 1178 p = &numbuf[sizeof(numbuf)]; 1179 for (tmp = 0; tmp < 2 || decpt ; tmp++) { 1180 *--p = '0' + decpt % 10; 1181 decpt /= 10; 1182 } 1183 tmp = &numbuf[sizeof(numbuf)] - p; 1184 (void) memcpy(s, p, tmp); 1185 s += tmp; 1186 } 1187 1188 len = s - fpbuf; 1189 s = fpbuf; 1190 precision = len; 1191 break; 1192 } 1193 #endif /* FP */ 1194 1195 case 's': 1196 if (!(s = va_arg(args, char *))) 1197 s = nulls; 1198 len = strlen(s); 1199 break; 1200 1201 case 'c': 1202 flags &= ~FL_DOT; 1203 numbuf[0] = va_arg(args, int); 1204 s = numbuf; 1205 len = 1; 1206 break; 1207 1208 case '%': 1209 default: 1210 numbuf[0] = c; 1211 s = numbuf; 1212 len = 1; 1213 break; 1214 } 1215 1216 /* 1217 * At this point s should point to a string that is 1218 * to be formatted, and len should be the length of the 1219 * string. 1220 */ 1221 if (!(flags & FL_DOT) || len < precision) 1222 precision = len; 1223 if (field > precision) { 1224 field -= precision; 1225 if (!(flags & FL_RIGHT)) { 1226 field = -field; 1227 /* skip past sign or 0x when padding with 0 */ 1228 if ((flags & FL_ZERO) && (flags & FL_NUMBER)) { 1229 if (*s == '+' || *s == '-' || *s ==' ') 1230 { 1231 shf_putc(*s, shf); 1232 s++; 1233 precision--; 1234 nwritten++; 1235 } else if (*s == '0') { 1236 shf_putc(*s, shf); 1237 s++; 1238 nwritten++; 1239 if (--precision > 0 && 1240 (*s | 0x20) == 'x') 1241 { 1242 shf_putc(*s, shf); 1243 s++; 1244 precision--; 1245 nwritten++; 1246 } 1247 } 1248 c = '0'; 1249 } else 1250 c = flags & FL_ZERO ? '0' : ' '; 1251 if (field < 0) { 1252 nwritten += -field; 1253 for ( ; field < 0 ; field++) 1254 shf_putc(c, shf); 1255 } 1256 } else 1257 c = ' '; 1258 } else 1259 field = 0; 1260 1261 if (precision > 0) { 1262 nwritten += precision; 1263 for ( ; precision-- > 0 ; s++) 1264 shf_putc(*s, shf); 1265 } 1266 if (field > 0) { 1267 nwritten += field; 1268 for ( ; field > 0 ; --field) 1269 shf_putc(c, shf); 1270 } 1271 } 1272 1273 return shf_error(shf) ? EOF : nwritten; 1274 } 1275