Tried to fix whole execution system (Shell, Unnamed Pipes)
[meinos.git] / apps / lib / stdlibc / stdio.c
blobc2a9a4437dc80e6995a121c7c521a67db50fba98
1 /*
2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <stdarg.h>
22 #include <syscall.h>
23 #include <errno.h>
24 #include <stdio.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <limits.h>
29 #define check_stream(stream) ((stream)!=NULL && (stream)->fh>=0)
31 static FILE *create_stream(int fh,int oflag) {
32 FILE *stream = malloc(sizeof(FILE));
33 stream->fh = fh;
34 stream->oflag = oflag;
35 stream->error = 0;
36 stream->eof = 0;
37 stream->buf = malloc(BUFSIZ);
38 stream->bufcur = stream->buf;
39 stream->dobuf = 1;
40 return stream;
43 static void stdio_exit() {
44 fflush(stdout);
45 fflush(stderr);
46 fclose(stdin);
47 fclose(stdout);
48 fclose(stderr);
51 /**
52 * Initializes stdio
54 void stdio_init() {
55 stdin = create_stream(STDIN_FILENO,O_RDONLY);
56 stdout = create_stream(STDOUT_FILENO,O_WRONLY);
57 stderr = create_stream(STDERR_FILENO,O_WRONLY);
58 atexit(stdio_exit);
61 /**
62 * Converts a oflag string to a oflag number
63 * @param oflag Mode string
64 * @return Mode number
65 * @todo fix
67 static int oflag_str2num(const char *oflag) {
68 int m;
69 if (oflag[0]=='r') m = O_RDONLY;
70 else if (oflag[0]=='w') m = O_CREAT|O_WRONLY|O_TRUNC;
71 else if (oflag[0]=='a') m = O_CREAT|O_APPEND|O_TRUNC;
72 else m = -1;
73 if (oflag[1]=='+' && m!=-1) m |= O_RDONLY|O_WRONLY;
74 return m;
77 /**
78 * Creates a name for a temporary file
79 * @param s Buffer
80 * @return Filename
82 char *tmpnam(char *buf1) {
83 static unsigned int tmp_num = 0;
84 static char *buf2[L_tmpnam];
85 char *buf = buf1!=NULL?buf1:memset(buf2,0,L_tmpnam);
86 snprintf(buf,L_tmpnam,"%s/%04x",P_tmpdir,tmp_num++);
87 return buf;
90 /**
91 * Clears error in file
92 * @param file Filehandle
94 void clearerr(FILE *file) {
95 file->error = 0;
98 /**
99 * Gets whether stream reached EOF
100 * @param stream Stream
101 * @return !=0 if EOF
103 int feof(FILE *stream) {
104 if (check_stream(stream)) return stream->eof;
105 else {
106 errno = EBADF;
107 return 0;
112 * Gets current error of stream
113 * @param steam Stream
114 * @return Error number
116 int ferror(FILE *stream) {
117 if (check_stream(stream)) return stream->error;
118 else {
119 errno = EBADF;
120 return 0;
125 * Closes file
126 * @param stream Stream
127 * @return 0=success; -1=failure
129 int fclose(FILE *stream) {
130 if (check_stream(stream)) {
131 if (fflush(stream)==0) {
132 if (close(stream->fh)==0) {
133 free(stream->buf);
134 free(stream);
138 else errno = EBADF;
139 return -1;
143 * Opens a file with Filedescriptor
144 * @param fh Filedescriptor
145 * @param oflag Mode
146 * @return Filehandle
148 FILE *fdopen(int fh,const char *oflag) {
149 return create_stream(fh,oflag_str2num(oflag));
153 * Maps a stream pointer to a file descriptor
154 * @param stream Stream
155 * @return Filedescriptor
157 int fileno(FILE *stream) {
158 if (check_stream(stream)) return stream->fh;
159 else {
160 errno = EBADF;
161 return 0;
166 * Opens a file
167 * @param name Path to file
168 * @param oflag Mode
169 * @return Filehandle
170 * @todo truncate
172 FILE *fopen(const char *name,const char *oflag) {
173 int m = oflag_str2num(oflag);
174 if (m>0) {
175 int fh = open(name,m,0777);
176 if (fh>=0) {
177 if ((m&O_TRUNC)) ftruncate(fh,0);
178 return create_stream(fh,m);
181 return NULL;
185 * Flushs a stream
186 * @param stream Stream to flush
187 * @return Success?
189 int fflush(FILE *stream) {
190 if (stream->dobuf) {
191 int ret;
192 #ifdef _STDIO_DEBUG
193 if (stream->fh==STDOUT_FILENO) ret = syscall_call(SYSCALL_PUTSN,3,0,stream->buf,stream->bufcur-stream->buf)==-1?EOF:0;
194 else if (stream->fh==STDERR_FILENO) ret = syscall_call(SYSCALL_PUTSN,3,1,stream->buf,stream->bufcur-stream->buf)==-1?EOF:0;
195 else {
196 #endif
197 ret = write(stream->fh,stream->buf,stream->bufcur-stream->buf);
198 if (ret>0 && ret<(stream->bufcur-stream->buf)) {
199 stream->eof = 1;
200 ret = EOF;
202 #ifdef _STDIO_DEBUG
204 #endif
205 stream->bufcur = stream->buf;
206 return ret;
208 return 0;
212 * Print string to stdout
213 * @param s String
214 * @return How many bytes put
216 int puts(const char *s) {
217 int ret = fputs(s,stdout);
218 if (ret>0) {
219 putchar('\n');
220 ret++;
222 return ret;
226 * Writes binary
227 * @param ptr Buffer to get data from
228 * @param size How many bytes to write
229 * @param stream Stream to write to
230 * @return How many elements written
232 size_t _fwrite(const void *ptr,size_t size,FILE *stream) {
233 if (size==0) return 0;
234 if (check_stream(stream)) {
235 if (stream->oflag&O_WRONLY) {
236 if (stream->dobuf /*&& size<BUFSIZ*/) {
237 if (stream->bufcur+size>stream->buf+BUFSIZ) fflush(stream);
238 if (size>BUFSIZ) size = BUFSIZ;
239 memcpy(stream->bufcur,ptr,size);
240 stream->bufcur += size;
241 if (memchr(ptr,'\n',size)!=NULL) fflush(stream);
242 return size;
244 else {
245 int ret = write(stream->fh,ptr,size);
246 if (ret>0 && ret<(stream->bufcur-stream->buf)) stream->eof = 1;
247 return ret;
250 else {
251 stream->eof = 1;
252 return 0;
255 else {
256 errno = EBADF;
257 return -1;
262 * Gets string from file
263 * @param s Destination for string
264 * @param n How many bytes to read
265 * @param stream Stream to read from
266 * @return String
268 char *fgets(char *s,int n,FILE *stream) {
269 int i,chr;
270 if (check_stream(stream)) {
271 for (i=0;i<n-1;i++) {
272 chr = fgetc(stream);
273 if (chr==EOF) break;
274 else s[i] = chr;
275 if (errno>0) {
276 stream->error = errno;
277 return NULL;
279 if (s[i]==0 || s[i]=='\n') break;
281 s[i] = 0;
282 return s;
284 else {
285 errno = EBADF;
286 return NULL;
291 * Reads binary
292 * @param ptr Buffer to store data
293 * @param size How many bytes to read
294 * @param stream Stream to read from
295 * @return How many elements read
297 size_t _fread(void *ptr,size_t size,FILE *stream) {
298 if (check_stream(stream)) {
299 ssize_t ret;
300 ret = read(stream->fh,ptr,size);
301 if (ret>0) {
302 if (ret<size) stream->eof = 1;
303 return ret;
305 else return -1;
307 else {
308 errno = EBADF;
309 return -1;
313 int fgetpos(FILE *stream,fpos_t *pos) {
314 if (check_stream(stream)) {
315 *pos = ftello(stream);
316 return 0;
318 else {
319 errno = EBADF;
320 return -1;
324 int fsetpos(FILE *stream,fpos_t *pos) {
325 if (check_stream(stream)) {
326 fseeko(stream,*pos,SEEK_SET);
327 return 0;
329 else {
330 errno = EBADF;
331 return -1;
335 FILE *freopen(const char *filename,const char *oflag,FILE *stream) {
336 if (check_stream(stream)) {
337 fflush(stream);
338 close(stream->fh);
339 stream->oflag = oflag_str2num(oflag);
340 stream->eof = 0;
341 stream->error = 0;
342 stream->fh = open(filename,stream->oflag);
343 return stream;
345 else {
346 errno = EBADF;
347 return NULL;
351 /// @todo Implement me
352 int fscanf(FILE *stream,const char *format,...) {
353 return 0;
356 /// @todo Implement me
357 int ungetc(int c,FILE *stream) {
358 return 0;