xref: /minix3/lib/libc/stdio/freopen.c (revision b6cbf7203b080219de306404f8022a65b7884f33)
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, 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 	/* Find the slot the stream had, if any. */
43 	for(i = 0; i < FOPEN_MAX; i++)
44 		if (stream == __iotab[i])
45 			break;
46 
47 	/* If none, it might've been fclose()d; find a new slot for it. */
48 	if(i >= FOPEN_MAX) {
49 	        for (i = 0; __iotab[i] != 0 ; i++) {
50                 	if ( i >= FOPEN_MAX-1 )
51                         	return (FILE *)NULL;
52 		}
53 	}
54 
55 	/* If it was valid, it isn't any more until the freopen() succeeds. */
56 	__iotab[i] = 0;
57 
58 	switch(*mode++) {
59 	case 'r':
60 		flags |= _IOREAD;
61 		rwmode = O_RDONLY;
62 		break;
63 	case 'w':
64 		flags |= _IOWRITE;
65 		rwmode = O_WRONLY;
66 		rwflags = O_CREAT | O_TRUNC;
67 		break;
68 	case 'a':
69 		flags |= _IOWRITE | _IOAPPEND;
70 		rwmode = O_WRONLY;
71 		rwflags |= O_APPEND | O_CREAT;
72 		break;
73 	default:
74 		goto loser;
75 	}
76 
77 	while (*mode) {
78 		switch(*mode++) {
79 		case 'b':
80 			continue;
81 		case '+':
82 			rwmode = O_RDWR;
83 			flags |= _IOREAD | _IOWRITE;
84 			continue;
85 		/* The sequence may be followed by aditional characters */
86 		default:
87 			break;
88 		}
89 		break;
90 	}
91 
92 	if ((rwflags & O_TRUNC)
93 	    || (((fd = _open(name, rwmode)) < 0)
94 		    && (rwflags & O_CREAT))) {
95 		if (((fd = _creat(name, PMODE)) < 0) && flags | _IOREAD) {
96 			(void) _close(fd);
97 			fd = _open(name, rwmode);
98 		}
99 	}
100 
101 	if (fd < 0) {
102 		goto loser;
103 	}
104 
105 	if ( fstat( fd, &st ) == 0 ) {
106 		if ( S_ISFIFO(st.st_mode) ) flags |= _IOFIFO;
107 	} else {
108 		goto loser;
109 	}
110 
111 	stream->_count = 0;
112 	stream->_fd = fd;
113 	stream->_flags = flags;
114 	__iotab[i] = stream;
115 	return stream;
116 
117 loser:
118 	if (stream != stdin && stream != stdout && stream != stderr)
119 		free((void *)stream);
120 	return (FILE *)NULL;
121 }
122