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