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