1 /* $OpenBSD: shf.c,v 1.16 2013/04/19 17:36:09 millert Exp $ */ 2 3 /*- 4 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 5 * 2012, 2013, 2015, 2016, 2017 6 * mirabilos <m (at) mirbsd.org> 7 * 8 * Provided that these terms and disclaimer and all copyright notices 9 * are retained or reproduced in an accompanying document, permission 10 * is granted to deal in this work without restriction, including un- 11 * limited rights to use, publicly perform, distribute, sell, modify, 12 * merge, give away, or sublicence. 13 * 14 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 15 * the utmost extent permitted by applicable law, neither express nor 16 * implied; without malicious intent or gross negligence. In no event 17 * may a licensor, author or contributor be held liable for indirect, 18 * direct, other damage, loss, or other issues arising in any way out 19 * of dealing in the work, even if advised of the possibility of such 20 * damage or existence of a defect, except proven that it results out 21 * of said person's immediate fault when using the work as intended. 22 *- 23 * Use %zX instead of %p and floating point isn't supported at all. 24 */ 25 26 #include "sh.h" 27 28 __RCSID("$MirOS: src/bin/mksh/shf.c,v 1.79 2017/04/12 17:08:49 tg Exp $"); 29 30 /* flags to shf_emptybuf() */ 31 #define EB_READSW 0x01 /* about to switch to reading */ 32 #define EB_GROW 0x02 /* grow buffer if necessary (STRING+DYNAMIC) */ 33 34 /* 35 * Replacement stdio routines. Stdio is too flakey on too many machines 36 * to be useful when you have multiple processes using the same underlying 37 * file descriptors. 38 */ 39 40 static int shf_fillbuf(struct shf *); 41 static int shf_emptybuf(struct shf *, int); 42 43 /* 44 * Open a file. First three args are for open(), last arg is flags for 45 * this package. Returns NULL if file could not be opened, or if a dup 46 * fails. 47 */ 48 struct shf * 49 shf_open(const char *name, int oflags, int mode, int sflags) 50 { 51 struct shf *shf; 52 ssize_t bsize = 53 /* at most 512 */ 54 sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE; 55 int fd, eno; 56 57 /* Done before open so if alloca fails, fd won't be lost. */ 58 shf = alloc(sizeof(struct shf) + bsize, ATEMP); 59 shf->areap = ATEMP; 60 shf->buf = (unsigned char *)&shf[1]; 61 shf->bsize = bsize; 62 shf->flags = SHF_ALLOCS; 63 /* Rest filled in by reopen. */ 64 65 fd = binopen3(name, oflags, mode); 66 if (fd < 0) { 67 eno = errno; 68 afree(shf, shf->areap); 69 errno = eno; 70 return (NULL); 71 } 72 if ((sflags & SHF_MAPHI) && fd < FDBASE) { 73 int nfd; 74 75 nfd = fcntl(fd, F_DUPFD, FDBASE); 76 eno = errno; 77 close(fd); 78 if (nfd < 0) { 79 afree(shf, shf->areap); 80 errno = eno; 81 return (NULL); 82 } 83 fd = nfd; 84 } 85 sflags &= ~SHF_ACCMODE; 86 sflags |= (oflags & O_ACCMODE) == O_RDONLY ? SHF_RD : 87 ((oflags & O_ACCMODE) == O_WRONLY ? SHF_WR : SHF_RDWR); 88 89 return (shf_reopen(fd, sflags, shf)); 90 } 91 92 /* helper function for shf_fdopen and shf_reopen */ 93 static void 94 shf_open_hlp(int fd, int *sflagsp, const char *where) 95 { 96 int sflags = *sflagsp; 97 98 /* use fcntl() to figure out correct read/write flags */ 99 if (sflags & SHF_GETFL) { 100 int flags = fcntl(fd, F_GETFL, 0); 101 102 if (flags < 0) 103 /* will get an error on first read/write */ 104 sflags |= SHF_RDWR; 105 else { 106 switch (flags & O_ACCMODE) { 107 case O_RDONLY: 108 sflags |= SHF_RD; 109 break; 110 case O_WRONLY: 111 sflags |= SHF_WR; 112 break; 113 case O_RDWR: 114 sflags |= SHF_RDWR; 115 break; 116 } 117 } 118 *sflagsp = sflags; 119 } 120 121 if (!(sflags & (SHF_RD | SHF_WR))) 122 internal_errorf(Tf_sD_s, where, "missing read/write"); 123 } 124 125 /* Set up the shf structure for a file descriptor. Doesn't fail. */ 126 struct shf * 127 shf_fdopen(int fd, int sflags, struct shf *shf) 128 { 129 ssize_t bsize = 130 /* at most 512 */ 131 sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE; 132 133 shf_open_hlp(fd, &sflags, "shf_fdopen"); 134 if (shf) { 135 if (bsize) { 136 shf->buf = alloc(bsize, ATEMP); 137 sflags |= SHF_ALLOCB; 138 } else 139 shf->buf = NULL; 140 } else { 141 shf = alloc(sizeof(struct shf) + bsize, ATEMP); 142 shf->buf = (unsigned char *)&shf[1]; 143 sflags |= SHF_ALLOCS; 144 } 145 shf->areap = ATEMP; 146 shf->fd = fd; 147 shf->rp = shf->wp = shf->buf; 148 shf->rnleft = 0; 149 shf->rbsize = bsize; 150 shf->wnleft = 0; /* force call to shf_emptybuf() */ 151 shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize; 152 shf->flags = sflags; 153 shf->errnosv = 0; 154 shf->bsize = bsize; 155 if (sflags & SHF_CLEXEC) 156 fcntl(fd, F_SETFD, FD_CLOEXEC); 157 return (shf); 158 } 159 160 /* Set up an existing shf (and buffer) to use the given fd */ 161 struct shf * 162 shf_reopen(int fd, int sflags, struct shf *shf) 163 { 164 ssize_t bsize = 165 /* at most 512 */ 166 sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE; 167 168 shf_open_hlp(fd, &sflags, "shf_reopen"); 169 if (!shf || !shf->buf || shf->bsize < bsize) 170 internal_errorf(Tf_sD_s, "shf_reopen", Tbad_bsize); 171 172 /* assumes shf->buf and shf->bsize already set up */ 173 shf->fd = fd; 174 shf->rp = shf->wp = shf->buf; 175 shf->rnleft = 0; 176 shf->rbsize = bsize; 177 shf->wnleft = 0; /* force call to shf_emptybuf() */ 178 shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize; 179 shf->flags = (shf->flags & (SHF_ALLOCS | SHF_ALLOCB)) | sflags; 180 shf->errnosv = 0; 181 if (sflags & SHF_CLEXEC) 182 fcntl(fd, F_SETFD, FD_CLOEXEC); 183 return (shf); 184 } 185 186 /* 187 * Open a string for reading or writing. If reading, bsize is the number 188 * of bytes that can be read. If writing, bsize is the maximum number of 189 * bytes that can be written. If shf is not NULL, it is filled in and 190 * returned, if it is NULL, shf is allocated. If writing and buf is NULL 191 * and SHF_DYNAMIC is set, the buffer is allocated (if bsize > 0, it is 192 * used for the initial size). Doesn't fail. 193 * When writing, a byte is reserved for a trailing NUL - see shf_sclose(). 194 */ 195 struct shf * 196 shf_sopen(char *buf, ssize_t bsize, int sflags, struct shf *shf) 197 { 198 /* can't have a read+write string */ 199 if (!(!(sflags & SHF_RD) ^ !(sflags & SHF_WR))) 200 internal_errorf(Tf_flags, "shf_sopen", 201 (unsigned int)sflags); 202 203 if (!shf) { 204 shf = alloc(sizeof(struct shf), ATEMP); 205 sflags |= SHF_ALLOCS; 206 } 207 shf->areap = ATEMP; 208 if (!buf && (sflags & SHF_WR) && (sflags & SHF_DYNAMIC)) { 209 if (bsize <= 0) 210 bsize = 64; 211 sflags |= SHF_ALLOCB; 212 buf = alloc(bsize, shf->areap); 213 } 214 shf->fd = -1; 215 shf->buf = shf->rp = shf->wp = (unsigned char *)buf; 216 shf->rnleft = bsize; 217 shf->rbsize = bsize; 218 shf->wnleft = bsize - 1; /* space for a '\0' */ 219 shf->wbsize = bsize; 220 shf->flags = sflags | SHF_STRING; 221 shf->errnosv = 0; 222 shf->bsize = bsize; 223 224 return (shf); 225 } 226 227 /* Flush and close file descriptor, free the shf structure */ 228 int 229 shf_close(struct shf *shf) 230 { 231 int ret = 0; 232 233 if (shf->fd >= 0) { 234 ret = shf_flush(shf); 235 if (close(shf->fd) < 0) 236 ret = -1; 237 } 238 if (shf->flags & SHF_ALLOCS) 239 afree(shf, shf->areap); 240 else if (shf->flags & SHF_ALLOCB) 241 afree(shf->buf, shf->areap); 242 243 return (ret); 244 } 245 246 /* Flush and close file descriptor, don't free file structure */ 247 int 248 shf_fdclose(struct shf *shf) 249 { 250 int ret = 0; 251 252 if (shf->fd >= 0) { 253 ret = shf_flush(shf); 254 if (close(shf->fd) < 0) 255 ret = -1; 256 shf->rnleft = 0; 257 shf->rp = shf->buf; 258 shf->wnleft = 0; 259 shf->fd = -1; 260 } 261 262 return (ret); 263 } 264 265 /* 266 * Close a string - if it was opened for writing, it is NUL terminated; 267 * returns a pointer to the string and frees shf if it was allocated 268 * (does not free string if it was allocated). 269 */ 270 char * 271 shf_sclose(struct shf *shf) 272 { 273 unsigned char *s = shf->buf; 274 275 /* NUL terminate */ 276 if (shf->flags & SHF_WR) { 277 shf->wnleft++; 278 shf_putc('\0', shf); 279 } 280 if (shf->flags & SHF_ALLOCS) 281 afree(shf, shf->areap); 282 return ((char *)s); 283 } 284 285 /* 286 * Un-read what has been read but not examined, or write what has been 287 * buffered. Returns 0 for success, -1 for (write) error. 288 */ 289 int 290 shf_flush(struct shf *shf) 291 { 292 int rv = 0; 293 294 if (shf->flags & SHF_STRING) 295 rv = (shf->flags & SHF_WR) ? -1 : 0; 296 else if (shf->fd < 0) 297 internal_errorf(Tf_sD_s, "shf_flush", "no fd"); 298 else if (shf->flags & SHF_ERROR) { 299 errno = shf->errnosv; 300 rv = -1; 301 } else if (shf->flags & SHF_READING) { 302 shf->flags &= ~(SHF_EOF | SHF_READING); 303 if (shf->rnleft > 0) { 304 if (lseek(shf->fd, (off_t)-shf->rnleft, 305 SEEK_CUR) == -1) { 306 shf->flags |= SHF_ERROR; 307 shf->errnosv = errno; 308 rv = -1; 309 } 310 shf->rnleft = 0; 311 shf->rp = shf->buf; 312 } 313 } else if (shf->flags & SHF_WRITING) 314 rv = shf_emptybuf(shf, 0); 315 316 return (rv); 317 } 318 319 /* 320 * Write out any buffered data. If currently reading, flushes the read 321 * buffer. Returns 0 for success, -1 for (write) error. 322 */ 323 static int 324 shf_emptybuf(struct shf *shf, int flags) 325 { 326 int ret = 0; 327 328 if (!(shf->flags & SHF_STRING) && shf->fd < 0) 329 internal_errorf(Tf_sD_s, "shf_emptybuf", "no fd"); 330 331 if (shf->flags & SHF_ERROR) { 332 errno = shf->errnosv; 333 return (-1); 334 } 335 336 if (shf->flags & SHF_READING) { 337 if (flags & EB_READSW) 338 /* doesn't happen */ 339 return (0); 340 ret = shf_flush(shf); 341 shf->flags &= ~SHF_READING; 342 } 343 if (shf->flags & SHF_STRING) { 344 unsigned char *nbuf; 345 346 /* 347 * Note that we assume SHF_ALLOCS is not set if 348 * SHF_ALLOCB is set... (changing the shf pointer could 349 * cause problems) 350 */ 351 if (!(flags & EB_GROW) || !(shf->flags & SHF_DYNAMIC) || 352 !(shf->flags & SHF_ALLOCB)) 353 return (-1); 354 /* allocate more space for buffer */ 355 nbuf = aresize2(shf->buf, 2, shf->wbsize, shf->areap); 356 shf->rp = nbuf + (shf->rp - shf->buf); 357 shf->wp = nbuf + (shf->wp - shf->buf); 358 shf->rbsize += shf->wbsize; 359 shf->wnleft += shf->wbsize; 360 shf->wbsize <<= 1; 361 shf->buf = nbuf; 362 } else { 363 if (shf->flags & SHF_WRITING) { 364 ssize_t n, ntowrite = shf->wp - shf->buf; 365 unsigned char *buf = shf->buf; 366 367 while (ntowrite > 0) { 368 n = write(shf->fd, buf, ntowrite); 369 if (n < 0) { 370 if (errno == EINTR && 371 !(shf->flags & SHF_INTERRUPT)) 372 continue; 373 shf->flags |= SHF_ERROR; 374 shf->errnosv = errno; 375 shf->wnleft = 0; 376 if (buf != shf->buf) { 377 /* 378 * allow a second flush 379 * to work 380 */ 381 memmove(shf->buf, buf, 382 ntowrite); 383 shf->wp = shf->buf + ntowrite; 384 } 385 return (-1); 386 } 387 buf += n; 388 ntowrite -= n; 389 } 390 if (flags & EB_READSW) { 391 shf->wp = shf->buf; 392 shf->wnleft = 0; 393 shf->flags &= ~SHF_WRITING; 394 return (0); 395 } 396 } 397 shf->wp = shf->buf; 398 shf->wnleft = shf->wbsize; 399 } 400 shf->flags |= SHF_WRITING; 401 402 return (ret); 403 } 404 405 /* Fill up a read buffer. Returns -1 for a read error, 0 otherwise. */ 406 static int 407 shf_fillbuf(struct shf *shf) 408 { 409 ssize_t n; 410 411 if (shf->flags & SHF_STRING) 412 return (0); 413 414 if (shf->fd < 0) 415 internal_errorf(Tf_sD_s, "shf_fillbuf", "no fd"); 416 417 if (shf->flags & (SHF_EOF | SHF_ERROR)) { 418 if (shf->flags & SHF_ERROR) 419 errno = shf->errnosv; 420 return (-1); 421 } 422 423 if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == -1) 424 return (-1); 425 426 shf->flags |= SHF_READING; 427 428 shf->rp = shf->buf; 429 while (/* CONSTCOND */ 1) { 430 n = blocking_read(shf->fd, (char *)shf->buf, shf->rbsize); 431 if (n < 0 && errno == EINTR && !(shf->flags & SHF_INTERRUPT)) 432 continue; 433 break; 434 } 435 if (n < 0) { 436 shf->flags |= SHF_ERROR; 437 shf->errnosv = errno; 438 shf->rnleft = 0; 439 shf->rp = shf->buf; 440 return (-1); 441 } 442 if ((shf->rnleft = n) == 0) 443 shf->flags |= SHF_EOF; 444 return (0); 445 } 446 447 /* 448 * Read a buffer from shf. Returns the number of bytes read into buf, if 449 * no bytes were read, returns 0 if end of file was seen, -1 if a read 450 * error occurred. 451 */ 452 ssize_t 453 shf_read(char *buf, ssize_t bsize, struct shf *shf) 454 { 455 ssize_t ncopy, orig_bsize = bsize; 456 457 if (!(shf->flags & SHF_RD)) 458 internal_errorf(Tf_flags, Tshf_read, 459 (unsigned int)shf->flags); 460 461 if (bsize <= 0) 462 internal_errorf(Tf_szs, Tshf_read, bsize, Tbsize); 463 464 while (bsize > 0) { 465 if (shf->rnleft == 0 && 466 (shf_fillbuf(shf) == -1 || shf->rnleft == 0)) 467 break; 468 ncopy = shf->rnleft; 469 if (ncopy > bsize) 470 ncopy = bsize; 471 memcpy(buf, shf->rp, ncopy); 472 buf += ncopy; 473 bsize -= ncopy; 474 shf->rp += ncopy; 475 shf->rnleft -= ncopy; 476 } 477 /* Note: fread(3S) returns 0 for errors - this doesn't */ 478 return (orig_bsize == bsize ? (shf_error(shf) ? -1 : 0) : 479 orig_bsize - bsize); 480 } 481 482 /* 483 * Read up to a newline or -1. The newline is put in buf; buf is always 484 * NUL terminated. Returns NULL on read error or if nothing was read 485 * before end of file, returns a pointer to the NUL byte in buf 486 * otherwise. 487 */ 488 char * 489 shf_getse(char *buf, ssize_t bsize, struct shf *shf) 490 { 491 unsigned char *end; 492 ssize_t ncopy; 493 char *orig_buf = buf; 494 495 if (!(shf->flags & SHF_RD)) 496 internal_errorf(Tf_flags, "shf_getse", 497 (unsigned int)shf->flags); 498 499 if (bsize <= 0) 500 return (NULL); 501 502 /* save room for NUL */ 503 --bsize; 504 do { 505 if (shf->rnleft == 0) { 506 if (shf_fillbuf(shf) == -1) 507 return (NULL); 508 if (shf->rnleft == 0) { 509 *buf = '\0'; 510 return (buf == orig_buf ? NULL : buf); 511 } 512 } 513 end = (unsigned char *)memchr((char *)shf->rp, '\n', 514 shf->rnleft); 515 ncopy = end ? end - shf->rp + 1 : shf->rnleft; 516 if (ncopy > bsize) 517 ncopy = bsize; 518 memcpy(buf, (char *) shf->rp, ncopy); 519 shf->rp += ncopy; 520 shf->rnleft -= ncopy; 521 buf += ncopy; 522 bsize -= ncopy; 523 #ifdef MKSH_WITH_TEXTMODE 524 if (end && buf > orig_buf + 1 && buf[-2] == '\r') { 525 buf--; 526 bsize++; 527 buf[-1] = '\n'; 528 } 529 #endif 530 } while (!end && bsize); 531 #ifdef MKSH_WITH_TEXTMODE 532 if (!bsize && buf[-1] == '\r') { 533 int c = shf_getc(shf); 534 if (c == '\n') 535 buf[-1] = '\n'; 536 else if (c != -1) 537 shf_ungetc(c, shf); 538 } 539 #endif 540 *buf = '\0'; 541 return (buf); 542 } 543 544 /* Returns the char read. Returns -1 for error and end of file. */ 545 int 546 shf_getchar(struct shf *shf) 547 { 548 if (!(shf->flags & SHF_RD)) 549 internal_errorf(Tf_flags, "shf_getchar", 550 (unsigned int)shf->flags); 551 552 if (shf->rnleft == 0 && (shf_fillbuf(shf) == -1 || shf->rnleft == 0)) 553 return (-1); 554 --shf->rnleft; 555 return (*shf->rp++); 556 } 557 558 /* 559 * Put a character back in the input stream. Returns the character if 560 * successful, -1 if there is no room. 561 */ 562 int 563 shf_ungetc(int c, struct shf *shf) 564 { 565 if (!(shf->flags & SHF_RD)) 566 internal_errorf(Tf_flags, "shf_ungetc", 567 (unsigned int)shf->flags); 568 569 if ((shf->flags & SHF_ERROR) || c == -1 || 570 (shf->rp == shf->buf && shf->rnleft)) 571 return (-1); 572 573 if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == -1) 574 return (-1); 575 576 if (shf->rp == shf->buf) 577 shf->rp = shf->buf + shf->rbsize; 578 if (shf->flags & SHF_STRING) { 579 /* 580 * Can unget what was read, but not something different; 581 * we don't want to modify a string. 582 */ 583 if ((int)(shf->rp[-1]) != c) 584 return (-1); 585 shf->flags &= ~SHF_EOF; 586 shf->rp--; 587 shf->rnleft++; 588 return (c); 589 } 590 shf->flags &= ~SHF_EOF; 591 *--(shf->rp) = c; 592 shf->rnleft++; 593 return (c); 594 } 595 596 /* 597 * Write a character. Returns the character if successful, -1 if the 598 * char could not be written. 599 */ 600 int 601 shf_putchar(int c, struct shf *shf) 602 { 603 if (!(shf->flags & SHF_WR)) 604 internal_errorf(Tf_flags, "shf_putchar", 605 (unsigned int)shf->flags); 606 607 if (c == -1) 608 return (-1); 609 610 if (shf->flags & SHF_UNBUF) { 611 unsigned char cc = (unsigned char)c; 612 ssize_t n; 613 614 if (shf->fd < 0) 615 internal_errorf(Tf_sD_s, "shf_putchar", "no fd"); 616 if (shf->flags & SHF_ERROR) { 617 errno = shf->errnosv; 618 return (-1); 619 } 620 while ((n = write(shf->fd, &cc, 1)) != 1) 621 if (n < 0) { 622 if (errno == EINTR && 623 !(shf->flags & SHF_INTERRUPT)) 624 continue; 625 shf->flags |= SHF_ERROR; 626 shf->errnosv = errno; 627 return (-1); 628 } 629 } else { 630 /* Flush deals with strings and sticky errors */ 631 if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == -1) 632 return (-1); 633 shf->wnleft--; 634 *shf->wp++ = c; 635 } 636 637 return (c); 638 } 639 640 /* 641 * Write a string. Returns the length of the string if successful, -1 642 * if the string could not be written. 643 */ 644 ssize_t 645 shf_puts(const char *s, struct shf *shf) 646 { 647 if (!s) 648 return (-1); 649 650 return (shf_write(s, strlen(s), shf)); 651 } 652 653 /* Write a buffer. Returns nbytes if successful, -1 if there is an error. */ 654 ssize_t 655 shf_write(const char *buf, ssize_t nbytes, struct shf *shf) 656 { 657 ssize_t n, ncopy, orig_nbytes = nbytes; 658 659 if (!(shf->flags & SHF_WR)) 660 internal_errorf(Tf_flags, Tshf_write, 661 (unsigned int)shf->flags); 662 663 if (nbytes < 0) 664 internal_errorf(Tf_szs, Tshf_write, nbytes, Tbytes); 665 666 /* Don't buffer if buffer is empty and we're writting a large amount. */ 667 if ((ncopy = shf->wnleft) && 668 (shf->wp != shf->buf || nbytes < shf->wnleft)) { 669 if (ncopy > nbytes) 670 ncopy = nbytes; 671 memcpy(shf->wp, buf, ncopy); 672 nbytes -= ncopy; 673 buf += ncopy; 674 shf->wp += ncopy; 675 shf->wnleft -= ncopy; 676 } 677 if (nbytes > 0) { 678 if (shf->flags & SHF_STRING) { 679 /* resize buffer until there's enough space left */ 680 while (nbytes > shf->wnleft) 681 if (shf_emptybuf(shf, EB_GROW) == -1) 682 return (-1); 683 /* then write everything into the buffer */ 684 } else { 685 /* flush deals with sticky errors */ 686 if (shf_emptybuf(shf, EB_GROW) == -1) 687 return (-1); 688 /* write chunks larger than window size directly */ 689 if (nbytes > shf->wbsize) { 690 ncopy = nbytes; 691 if (shf->wbsize) 692 ncopy -= nbytes % shf->wbsize; 693 nbytes -= ncopy; 694 while (ncopy > 0) { 695 n = write(shf->fd, buf, ncopy); 696 if (n < 0) { 697 if (errno == EINTR && 698 !(shf->flags & SHF_INTERRUPT)) 699 continue; 700 shf->flags |= SHF_ERROR; 701 shf->errnosv = errno; 702 shf->wnleft = 0; 703 /* 704 * Note: fwrite(3) returns 0 705 * for errors - this doesn't 706 */ 707 return (-1); 708 } 709 buf += n; 710 ncopy -= n; 711 } 712 } 713 /* ... and buffer the rest */ 714 } 715 if (nbytes > 0) { 716 /* write remaining bytes to buffer */ 717 memcpy(shf->wp, buf, nbytes); 718 shf->wp += nbytes; 719 shf->wnleft -= nbytes; 720 } 721 } 722 723 return (orig_nbytes); 724 } 725 726 ssize_t 727 shf_fprintf(struct shf *shf, const char *fmt, ...) 728 { 729 va_list args; 730 ssize_t n; 731 732 va_start(args, fmt); 733 n = shf_vfprintf(shf, fmt, args); 734 va_end(args); 735 736 return (n); 737 } 738 739 ssize_t 740 shf_snprintf(char *buf, ssize_t bsize, const char *fmt, ...) 741 { 742 struct shf shf; 743 va_list args; 744 ssize_t n; 745 746 if (!buf || bsize <= 0) 747 internal_errorf("shf_snprintf: buf %zX, bsize %zd", 748 (size_t)buf, bsize); 749 750 shf_sopen(buf, bsize, SHF_WR, &shf); 751 va_start(args, fmt); 752 n = shf_vfprintf(&shf, fmt, args); 753 va_end(args); 754 /* NUL terminates */ 755 shf_sclose(&shf); 756 return (n); 757 } 758 759 char * 760 shf_smprintf(const char *fmt, ...) 761 { 762 struct shf shf; 763 va_list args; 764 765 shf_sopen(NULL, 0, SHF_WR|SHF_DYNAMIC, &shf); 766 va_start(args, fmt); 767 shf_vfprintf(&shf, fmt, args); 768 va_end(args); 769 /* NUL terminates */ 770 return (shf_sclose(&shf)); 771 } 772 773 #define FL_HASH 0x001 /* '#' seen */ 774 #define FL_PLUS 0x002 /* '+' seen */ 775 #define FL_RIGHT 0x004 /* '-' seen */ 776 #define FL_BLANK 0x008 /* ' ' seen */ 777 #define FL_SHORT 0x010 /* 'h' seen */ 778 #define FL_LONG 0x020 /* 'l' seen */ 779 #define FL_ZERO 0x040 /* '0' seen */ 780 #define FL_DOT 0x080 /* '.' seen */ 781 #define FL_UPPER 0x100 /* format character was uppercase */ 782 #define FL_NUMBER 0x200 /* a number was formated %[douxefg] */ 783 #define FL_SIZET 0x400 /* 'z' seen */ 784 #define FM_SIZES 0x430 /* h/l/z mask */ 785 786 ssize_t 787 shf_vfprintf(struct shf *shf, const char *fmt, va_list args) 788 { 789 const char *s; 790 char c, *cp; 791 int tmp = 0, flags; 792 size_t field, precision, len; 793 unsigned long lnum; 794 /* %#o produces the longest output */ 795 char numbuf[(8 * sizeof(long) + 2) / 3 + 1 + /* NUL */ 1]; 796 /* this stuff for dealing with the buffer */ 797 ssize_t nwritten = 0; 798 799 #define VA(type) va_arg(args, type) 800 801 if (!fmt) 802 return (0); 803 804 while ((c = *fmt++)) { 805 if (c != '%') { 806 shf_putc(c, shf); 807 nwritten++; 808 continue; 809 } 810 /* 811 * This will accept flags/fields in any order - not just 812 * the order specified in printf(3), but this is the way 813 * _doprnt() seems to work (on BSD and SYSV). The only 814 * restriction is that the format character must come 815 * last :-). 816 */ 817 flags = 0; 818 field = precision = 0; 819 while ((c = *fmt++)) { 820 switch (c) { 821 case '#': 822 flags |= FL_HASH; 823 continue; 824 825 case '+': 826 flags |= FL_PLUS; 827 continue; 828 829 case '-': 830 flags |= FL_RIGHT; 831 continue; 832 833 case ' ': 834 flags |= FL_BLANK; 835 continue; 836 837 case '0': 838 if (!(flags & FL_DOT)) 839 flags |= FL_ZERO; 840 continue; 841 842 case '.': 843 flags |= FL_DOT; 844 precision = 0; 845 continue; 846 847 case '*': 848 tmp = VA(int); 849 if (tmp < 0) { 850 if (flags & FL_DOT) 851 precision = 0; 852 else { 853 field = (unsigned int)-tmp; 854 flags |= FL_RIGHT; 855 } 856 } else if (flags & FL_DOT) 857 precision = (unsigned int)tmp; 858 else 859 field = (unsigned int)tmp; 860 continue; 861 862 case 'l': 863 flags &= ~FM_SIZES; 864 flags |= FL_LONG; 865 continue; 866 867 case 'h': 868 flags &= ~FM_SIZES; 869 flags |= FL_SHORT; 870 continue; 871 872 case 'z': 873 flags &= ~FM_SIZES; 874 flags |= FL_SIZET; 875 continue; 876 } 877 if (ksh_isdigit(c)) { 878 bool overflowed = false; 879 880 tmp = ksh_numdig(c); 881 while (c = *fmt++, ksh_isdigit(c)) 882 if (notok2mul(2147483647, tmp, 10)) 883 overflowed = true; 884 else 885 tmp = tmp * 10 + ksh_numdig(c); 886 --fmt; 887 if (overflowed) 888 tmp = 0; 889 if (flags & FL_DOT) 890 precision = (unsigned int)tmp; 891 else 892 field = (unsigned int)tmp; 893 continue; 894 } 895 break; 896 } 897 898 if (!c) 899 /* nasty format */ 900 break; 901 902 if (ksh_isupper(c)) { 903 flags |= FL_UPPER; 904 c = ksh_tolower(c); 905 } 906 907 switch (c) { 908 case 'd': 909 case 'i': 910 if (flags & FL_SIZET) 911 lnum = (long)VA(ssize_t); 912 else if (flags & FL_LONG) 913 lnum = VA(long); 914 else if (flags & FL_SHORT) 915 lnum = (long)(short)VA(int); 916 else 917 lnum = (long)VA(int); 918 goto integral; 919 920 case 'o': 921 case 'u': 922 case 'x': 923 if (flags & FL_SIZET) 924 lnum = VA(size_t); 925 else if (flags & FL_LONG) 926 lnum = VA(unsigned long); 927 else if (flags & FL_SHORT) 928 lnum = (unsigned long)(unsigned short)VA(int); 929 else 930 lnum = (unsigned long)VA(unsigned int); 931 932 integral: 933 flags |= FL_NUMBER; 934 cp = numbuf + sizeof(numbuf); 935 *--cp = '\0'; 936 937 switch (c) { 938 case 'd': 939 case 'i': 940 if (0 > (long)lnum) { 941 lnum = -(long)lnum; 942 tmp = 1; 943 } else 944 tmp = 0; 945 /* FALLTHROUGH */ 946 case 'u': 947 do { 948 *--cp = digits_lc[lnum % 10]; 949 lnum /= 10; 950 } while (lnum); 951 952 if (c != 'u') { 953 if (tmp) 954 *--cp = '-'; 955 else if (flags & FL_PLUS) 956 *--cp = '+'; 957 else if (flags & FL_BLANK) 958 *--cp = ' '; 959 } 960 break; 961 962 case 'o': 963 do { 964 *--cp = digits_lc[lnum & 0x7]; 965 lnum >>= 3; 966 } while (lnum); 967 968 if ((flags & FL_HASH) && *cp != '0') 969 *--cp = '0'; 970 break; 971 972 case 'x': { 973 const char *digits = (flags & FL_UPPER) ? 974 digits_uc : digits_lc; 975 do { 976 *--cp = digits[lnum & 0xF]; 977 lnum >>= 4; 978 } while (lnum); 979 980 if (flags & FL_HASH) { 981 *--cp = (flags & FL_UPPER) ? 'X' : 'x'; 982 *--cp = '0'; 983 } 984 } 985 } 986 len = numbuf + sizeof(numbuf) - 1 - (s = cp); 987 if (flags & FL_DOT) { 988 if (precision > len) { 989 field = precision; 990 flags |= FL_ZERO; 991 } else 992 /* no loss */ 993 precision = len; 994 } 995 break; 996 997 case 's': 998 if ((s = VA(const char *)) == NULL) 999 s = "(null)"; 1000 else if (flags & FL_HASH) { 1001 print_value_quoted(shf, s); 1002 continue; 1003 } 1004 len = utf_mbswidth(s); 1005 break; 1006 1007 case 'c': 1008 flags &= ~FL_DOT; 1009 c = (char)(VA(int)); 1010 /* FALLTHROUGH */ 1011 1012 case '%': 1013 default: 1014 numbuf[0] = c; 1015 numbuf[1] = 0; 1016 s = numbuf; 1017 len = 1; 1018 break; 1019 } 1020 1021 /* 1022 * At this point s should point to a string that is to be 1023 * formatted, and len should be the length of the string. 1024 */ 1025 if (!(flags & FL_DOT) || len < precision) 1026 precision = len; 1027 if (field > precision) { 1028 field -= precision; 1029 if (!(flags & FL_RIGHT)) { 1030 /* skip past sign or 0x when padding with 0 */ 1031 if ((flags & FL_ZERO) && (flags & FL_NUMBER)) { 1032 if (*s == '+' || *s == '-' || 1033 *s == ' ') { 1034 shf_putc(*s, shf); 1035 s++; 1036 precision--; 1037 nwritten++; 1038 } else if (*s == '0') { 1039 shf_putc(*s, shf); 1040 s++; 1041 nwritten++; 1042 if (--precision && 1043 ksh_eq(*s, 'X', 'x')) { 1044 shf_putc(*s, shf); 1045 s++; 1046 precision--; 1047 nwritten++; 1048 } 1049 } 1050 c = '0'; 1051 } else 1052 c = flags & FL_ZERO ? '0' : ' '; 1053 nwritten += field; 1054 while (field--) 1055 shf_putc(c, shf); 1056 field = 0; 1057 } else 1058 c = ' '; 1059 } else 1060 field = 0; 1061 1062 nwritten += precision; 1063 precision = utf_skipcols(s, precision, &tmp) - s; 1064 while (precision--) 1065 shf_putc(*s++, shf); 1066 1067 nwritten += field; 1068 while (field--) 1069 shf_putc(c, shf); 1070 } 1071 1072 return (shf_error(shf) ? -1 : nwritten); 1073 } 1074 1075 #if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST) 1076 int 1077 shf_getc(struct shf *shf) 1078 { 1079 return (shf_getc_i(shf)); 1080 } 1081 1082 int 1083 shf_putc(int c, struct shf *shf) 1084 { 1085 return (shf_putc_i(c, shf)); 1086 } 1087 #endif 1088 1089 #ifdef DEBUG 1090 const char * 1091 cstrerror(int errnum) 1092 { 1093 #undef strerror 1094 return (strerror(errnum)); 1095 #define strerror dontuse_strerror /* poisoned */ 1096 } 1097 #elif !HAVE_STRERROR 1098 1099 #if HAVE_SYS_ERRLIST 1100 #if !HAVE_SYS_ERRLIST_DECL 1101 extern const int sys_nerr; 1102 extern const char * const sys_errlist[]; 1103 #endif 1104 #endif 1105 1106 const char * 1107 cstrerror(int errnum) 1108 { 1109 /* "Unknown error: " + sign + rough estimate + NUL */ 1110 static char errbuf[15 + 1 + (8 * sizeof(int) + 2) / 3 + 1]; 1111 1112 #if HAVE_SYS_ERRLIST 1113 if (errnum > 0 && errnum < sys_nerr && sys_errlist[errnum]) 1114 return (sys_errlist[errnum]); 1115 #endif 1116 1117 switch (errnum) { 1118 case 0: 1119 return ("Undefined error: 0"); 1120 case EPERM: 1121 return ("Operation not permitted"); 1122 case ENOENT: 1123 return ("No such file or directory"); 1124 #ifdef ESRCH 1125 case ESRCH: 1126 return ("No such process"); 1127 #endif 1128 #ifdef E2BIG 1129 case E2BIG: 1130 return ("Argument list too long"); 1131 #endif 1132 case ENOEXEC: 1133 return ("Exec format error"); 1134 case EBADF: 1135 return ("Bad file descriptor"); 1136 #ifdef ENOMEM 1137 case ENOMEM: 1138 return ("Cannot allocate memory"); 1139 #endif 1140 case EACCES: 1141 return ("Permission denied"); 1142 case EEXIST: 1143 return ("File exists"); 1144 case ENOTDIR: 1145 return ("Not a directory"); 1146 #ifdef EINVAL 1147 case EINVAL: 1148 return ("Invalid argument"); 1149 #endif 1150 #ifdef ELOOP 1151 case ELOOP: 1152 return ("Too many levels of symbolic links"); 1153 #endif 1154 default: 1155 shf_snprintf(errbuf, sizeof(errbuf), 1156 "Unknown error: %d", errnum); 1157 return (errbuf); 1158 } 1159 } 1160 #endif 1161