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