flushbuf.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * flushbuf.c - flush a buffer
  3. */
  4. /* $Id$ */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include "loc_incl.h"
  8. #include <sys/types.h>
  9. off_t _lseek(int fildes, off_t offset, int whence);
  10. int _write(int d, const char *buf, int nbytes);
  11. int _isatty(int d);
  12. extern void (*_clean)(void);
  13. static int
  14. do_write(int d, char *buf, int nbytes)
  15. {
  16. int c;
  17. /* POSIX actually allows write() to return a positive value less
  18. than nbytes, so loop ...
  19. */
  20. while ((c = _write(d, buf, nbytes)) > 0 && c < nbytes) {
  21. nbytes -= c;
  22. buf += c;
  23. }
  24. return c > 0;
  25. }
  26. int
  27. __flushbuf(int c, FILE * stream)
  28. {
  29. _clean = __cleanup;
  30. if (fileno(stream) < 0) return EOF;
  31. if (!io_testflag(stream, _IOWRITE)) return EOF;
  32. if (io_testflag(stream, _IOREADING) && !feof(stream)) return EOF;
  33. stream->_flags &= ~_IOREADING;
  34. stream->_flags |= _IOWRITING;
  35. if (!io_testflag(stream, _IONBF)) {
  36. if (!stream->_buf) {
  37. if (stream == stdout && _isatty(fileno(stdout))) {
  38. if (!(stream->_buf =
  39. (unsigned char *) malloc(BUFSIZ))) {
  40. stream->_flags |= _IONBF;
  41. } else {
  42. stream->_flags |= _IOLBF|_IOMYBUF;
  43. stream->_bufsiz = BUFSIZ;
  44. stream->_count = -1;
  45. }
  46. } else {
  47. if (!(stream->_buf =
  48. (unsigned char *) malloc(BUFSIZ))) {
  49. stream->_flags |= _IONBF;
  50. } else {
  51. stream->_flags |= _IOMYBUF;
  52. stream->_bufsiz = BUFSIZ;
  53. if (!io_testflag(stream, _IOLBF))
  54. stream->_count = BUFSIZ - 1;
  55. else stream->_count = -1;
  56. }
  57. }
  58. stream->_ptr = stream->_buf;
  59. }
  60. }
  61. if (io_testflag(stream, _IONBF)) {
  62. char c1 = c;
  63. stream->_count = 0;
  64. if (io_testflag(stream, _IOAPPEND)) {
  65. if (_lseek(fileno(stream), 0L, SEEK_END) == -1) {
  66. stream->_flags |= _IOERR;
  67. return EOF;
  68. }
  69. }
  70. if (_write(fileno(stream), &c1, 1) != 1) {
  71. stream->_flags |= _IOERR;
  72. return EOF;
  73. }
  74. return (unsigned char) c;
  75. } else if (io_testflag(stream, _IOLBF)) {
  76. *stream->_ptr++ = c;
  77. /* stream->_count has been updated in putc macro. */
  78. if (c == '\n' || stream->_count == -stream->_bufsiz) {
  79. int count = -stream->_count;
  80. stream->_ptr = stream->_buf;
  81. stream->_count = 0;
  82. if (io_testflag(stream, _IOAPPEND)) {
  83. if (_lseek(fileno(stream), 0L, SEEK_END) == -1) {
  84. stream->_flags |= _IOERR;
  85. return EOF;
  86. }
  87. }
  88. if (! do_write(fileno(stream), (char *)stream->_buf,
  89. count)) {
  90. stream->_flags |= _IOERR;
  91. return EOF;
  92. }
  93. }
  94. } else {
  95. int count = stream->_ptr - stream->_buf;
  96. stream->_count = stream->_bufsiz - 1;
  97. stream->_ptr = stream->_buf + 1;
  98. if (count > 0) {
  99. if (io_testflag(stream, _IOAPPEND)) {
  100. if (_lseek(fileno(stream), 0L, SEEK_END) == -1) {
  101. stream->_flags |= _IOERR;
  102. return EOF;
  103. }
  104. }
  105. if (! do_write(fileno(stream), (char *)stream->_buf, count)) {
  106. *(stream->_buf) = c;
  107. stream->_flags |= _IOERR;
  108. return EOF;
  109. }
  110. }
  111. *(stream->_buf) = c;
  112. }
  113. return (unsigned char) c;
  114. }