freopen.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /*
  2. * freopen.c - open a file and associate a stream with it
  3. */
  4. /* $Id$ */
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <fcntl.h>
  8. #include <unistd.h>
  9. #include "loc_incl.h"
  10. #define PMODE 0666
  11. /* Do not "optimize" this file to use the open with O_CREAT if the file
  12. * does not exist. The reason is given in fopen.c.
  13. */
  14. FILE *
  15. freopen(const char *name, const char *mode, FILE *stream)
  16. {
  17. register int i;
  18. int rwmode = 0, rwflags = 0;
  19. int fd, flags = stream->_flags & (_IONBF | _IOFBF | _IOLBF | _IOMYBUF);
  20. (void) fflush(stream); /* ignore errors */
  21. (void) close(fileno(stream));
  22. switch(*mode++) {
  23. case 'r':
  24. flags |= _IOREAD;
  25. rwmode = O_RDONLY;
  26. break;
  27. case 'w':
  28. flags |= _IOWRITE;
  29. rwmode = O_WRONLY;
  30. rwflags = O_CREAT | O_TRUNC;
  31. break;
  32. case 'a':
  33. flags |= _IOWRITE | _IOAPPEND;
  34. rwmode = O_WRONLY;
  35. rwflags |= O_APPEND | O_CREAT;
  36. break;
  37. default:
  38. return (FILE *)NULL;
  39. }
  40. while (*mode) {
  41. switch(*mode++) {
  42. case 'b':
  43. continue;
  44. case '+':
  45. rwmode = O_RDWR;
  46. flags |= _IOREAD | _IOWRITE;
  47. continue;
  48. /* The sequence may be followed by aditional characters */
  49. default:
  50. break;
  51. }
  52. break;
  53. }
  54. if ((rwflags & O_TRUNC)
  55. || (((fd = open(name, rwmode)) < 0)
  56. && (rwflags & O_CREAT))) {
  57. if (((fd = creat(name, PMODE)) < 0) && flags | _IOREAD) {
  58. (void) close(fd);
  59. fd = open(name, rwmode);
  60. }
  61. }
  62. if (fd < 0) {
  63. for( i = 0; i < FOPEN_MAX; i++) {
  64. if (stream == __iotab[i]) {
  65. __iotab[i] = 0;
  66. break;
  67. }
  68. }
  69. if (stream != stdin && stream != stdout && stream != stderr)
  70. free((void *)stream);
  71. return (FILE *)NULL;
  72. }
  73. stream->_count = 0;
  74. stream->_fd = fd;
  75. stream->_flags = flags;
  76. return stream;
  77. }