#define DEVICES_TIMER_H #include #include #include #include #include "stdio.h" #include #include #include #include #include #include "stabs.h" #ifdef DEBUG #include "clib/debug_protos.h" #else #define KPrintF(a,...) #endif /* objects in ___filelist */ #include struct filenode { struct MinNode node; FILE theFILE; }; /* own stuff */ extern struct MinList ___filelist; /* List of all fopen'ed files */ extern struct ExecBase * SysBase; extern unsigned *__BUFSIZE; /* * SBF: I put all functions into this file which are linked anyway if stdio is used. */ extern int __fflush(FILE *); extern void __seterrno(void); extern int * __errno; extern FILE **__sF; /* ** the internal storage */ StdFileDes **__stdfiledes; unsigned __stdfilesize; #ifdef __posix_threads__ unsigned __stdLock[2]; #endif /* The normal Amiga shell sets no process->pr_CES stream - * we use Open("*",MODE_NEWFILE) in this case */ static BPTR stderrdes; /* ** */ void _setup_file(StdFileDes *fp) { fp->lx_inuse = 1; if (IsInteractive(fp->lx_fh)) fp->lx_flags = LX_FILE | LX_ATTY; else fp->lx_flags = LX_FILE; fp->lx_fx = 0; } int isatty(int d) { StdFileDes *sfd = _lx_fhfromfd(d); return sfd ? (sfd->lx_flags & LX_ATTY) : 0; } /* ** */ static int _lx_addflags(int d, int oflags) { StdFileDes *sfd = _lx_fhfromfd(d); return sfd ? sfd->lx_oflags |= oflags : 0; } /** * convert fd to a StdFileDes */ StdFileDes *_lx_fhfromfd(int d) { if ((unsigned) d < __stdfilesize) { StdFileDes *sfd = __stdfiledes[d]; if (sfd && sfd->lx_inuse) { KPrintF("lx_fhfromfd %ld -> %ld [__stdfiledes=%ld, __stdfilecount=%ld]\n", d, sfd, __stdfiledes, __stdfilesize); return sfd; } } return NULL; } /** * Open the file stream for the file descriptor. */ FILE *fdopen(int filedes, const char *mode) { if (mode != NULL) { struct filenode *node = (struct filenode *) malloc(sizeof(*node)); if (node != NULL) { FILE * f = &node->theFILE; if ((f->_bf._base = (unsigned char *) malloc(*__BUFSIZE)) != NULL) { AddHead((struct List * )&___filelist, (struct Node * )&node->node); f->_p = 0; f->_r = 0; f->_w = 0; f->_flags = __SMBF; /* Buffer is malloc'ed */ if (isatty(filedes)) f->_flags |= __SLBF; /* set linebuffered flag */ if (_lx_addflags(filedes, *mode == 'a' ? O_APPEND : 0) & O_WRONLY) f->_flags |= __SWO; /* set write-only flag */ f->file = filedes; f->_bf._size = *__BUFSIZE; f->linebufsize = 0; f->tmpp = 0; f->tmpinc = 0; f->tmpdir = 0; f->name = 0; #ifdef __posix_threads__ f->__spinlock[0] = 0; #endif return f; } free(node); } } errno = ENOMEM; return NULL; } int __fclose(FILE * stream) { __STDIO_LOCK(stream); int error = __fflush(stream); if (stream->file >= 0) close(stream->file); if (stream->name != NULL && (stream->_flags & __BPTRS) == 0) /* file is temporary */ { BPTR cd = CurrentDir(stream->tmpdir); /* cd t: */ if (!DeleteFile((CONST_STRPTR)stream->name)) /* delete file */ { __seterrno(); error = 1; } free(stream->name); /* free filename */ stream->name = NULL; UnLock(CurrentDir(cd)); /* cd back, unlock t: */ } stream->file = 0; __STDIO_UNLOCK(stream); return error; } static StdFileDes * __mk_stdfiledes(BPTR fh) { StdFileDes *sfd = (StdFileDes *) malloc(sizeof(StdFileDes)); if (sfd) { __stdfiledes[__stdfilesize] = sfd; sfd->lx_pos = __stdfilesize++; sfd->lx_fh = fh; sfd->lx_oflags = O_WRONLY; _setup_file(sfd); sfd->lx_flags |= LX_SYS; } KPrintF("__mk_stdfiledes [__stdfiledes=%ld, __stdfilecount=%ld]\n", __stdfiledes, __stdfilesize); return sfd; } /* ** */ void __initstdio(void) { StdFileDes *sfd; #ifdef __KICK13__ __stdfilesize = 0; #endif if ((__stdfiledes = (StdFileDes **) malloc(3 * sizeof(StdFileDes *)))) { unsigned __bufsiz = *__BUFSIZE; *__BUFSIZE = 512; if ((sfd = __mk_stdfiledes(Input()))) { sfd->lx_oflags = O_RDONLY; *__BUFSIZE = __bufsiz; if ((sfd = __mk_stdfiledes(Output()))) { BPTR bstderr; struct Process * proc = (struct Process *) SysBase->ThisTask; #ifdef __KICK13__ struct CommandLineInterface * cli = (struct CommandLineInterface *)BADDR(proc->pr_CLI); bstderr = cli ? cli->cli_StandardOutput : 0; #else bstderr = proc->pr_CES; #endif if(bstderr == 0 && (!proc->pr_CLI || (bstderr = stderrdes = Open((CONST_STRPTR)"*", MODE_OLDFILE)) == 0)) bstderr = __stdfiledes[STDOUT_FILENO]->lx_fh; if ((sfd = __mk_stdfiledes(bstderr))) { { short flags; // fdopen stdin, stdout and stderr and make stderr unbuffered FILE **f = __sF, *err; if (((*f++ = fdopen(STDIN_FILENO, "r")) == NULL) || ((*f++ = fdopen(STDOUT_FILENO, "w")) == NULL)) exit(20); if ((*f = err = fdopen(STDERR_FILENO, "w")) == NULL) exit(20); *__BUFSIZE = 4; free(err->_bf._base); flags = err->_flags & ~(__SMBF | __SLBF); err->_flags = flags | __SNBF; err->_bf._base = err->unget; err->_bf._size = 3; } *__BUFSIZE = __bufsiz; return; } } } } exit(20); } /** * Close the file descriptor d. * * Located here since it's called from __exitstdio */ int close(int d) { StdFileDes *sfd = _lx_fhfromfd(d); if (sfd) { if (sfd->lx_fx) return sfd->lx_fx->lx_close(sfd); if (!(sfd->lx_inuse -= 1)) { if (!(sfd->lx_flags & LX_SYS)) { if (!Close(sfd->lx_fh)) { #ifndef __KICK13__ __seterrno(); return EOF; #endif } } } } return 0; } /** * Close the file handle stream. * * Located here since it's called from __exitstdio */ int fclose(FILE *stream) { struct filenode *node; int retval; if (!stream) { return EOF; } __STDIO_LOCK(stream); retval = __fclose(stream) ? EOF : 0; if (stream->_flags & __SMBF) /* Free buffer if necessary */ { free(stream->_bf._base); stream->_bf._base = NULL; } if (stream->_flags & __BPTRS) { Close((BPTR )stream->name); Close((BPTR )stream->tmpdir); } node = (struct filenode *) ((struct MinNode *) stream - 1); Remove((struct Node * )&node->node); free(node); __STDIO_UNLOCK(stream); return retval; } struct MinList ___filelist = { /* list of open files (fflush() needs also access) */ (struct MinNode *) &___filelist.mlh_Tail, NULL, (struct MinNode *) &___filelist.mlh_Head }; void __exitstdio(void) { int i, max; struct MinNode *node; while ((node = ___filelist.mlh_Head)->mln_Succ != NULL) { fclose(&((struct filenode *) node)->theFILE); } for (max = __stdfilesize, i = 0; i < max; i++) { StdFileDes *sfd = __stdfiledes[i]; if (sfd && sfd->lx_inuse) { sfd->lx_inuse = 1; // force closing close(i); } // free(sfd); // freed by __exitmalloc } // free(__stdfiledes); // freed by __exitmalloc if (stderrdes) Close(stderrdes); } ADD2INIT(__initstdio, -30); ADD2EXIT(__exitstdio, -30);