/* Eunuchs compatibility code. */ #include "io-defs.h" #include #include "gem-meth.h" #include "buf-meth.h" #include #include #include /* util fun for fopen and fdopen. return modified flags, suitable for shoving into the flags halfword of a streamoid, and set append_p if open in append mode. */ local int parse_open_mode(mode, flags, create_p, append_p) char * mode; int flags; int * create_p; /* if should create the file */ int * append_p; /* if should append to existing file */ { while (*mode) switch(*mode++) { case 'r': flags |= STR_INPUT_P; break; case 'w': flags |= STR_OUTPUT_P; *create_p = 1; break; case 'a': flags |= STR_OUTPUT_P; *append_p = 1; break; case 'b': flags &= ~STR_TEXT_P; break; case '+': flags |= (STR_INPUT_P | STR_OUTPUT_P); break; } return(flags); } /* another util, used by fopen and freopen */ local int open_internal(name, input_p, output_p, create_p, append_p) char * name; int input_p; int output_p; int create_p; int append_p; { int handle, Fopen_mode; /* if output-only and not append, do Fcreate rather than Fopen */ if (create_p && !input_p && !append_p) handle = Fcreate(name, 0); /* create with no funny mode bits */ else { if (!output_p) Fopen_mode = 0; /* read-only */ else if (input_p) /* read/write */ Fopen_mode = 2; else Fopen_mode = 1; /* write-only */ handle = Fopen(name, Fopen_mode); } if ((handle == ENOENT) && create_p) /* no such file */ { handle = Fcreate(name, 0); /* create it */ if ((handle >= 0) && input_p) /* need input too? */ { Fclose(handle); handle = Fopen(name, Fopen_mode); } } return(handle); } FILE * fopen(name, mode) char * name; char * mode; { int handle; int flags, input_p, output_p; int create_p = 0; int append_p = 0; struct streamoid * s; flags = parse_open_mode(mode, STR_BUFFERED_P | STR_TEXT_P, &create_p, &append_p); input_p = flags & STR_INPUT_P; output_p = flags & STR_OUTPUT_P; handle = open_internal(name, input_p, output_p, create_p, append_p); if (handle < -3) /* really an error? */ { errno = handle; return(NULL); } s = __make_stream(handle, flags, gem_method_selector, append_p); return((FILE * )s); } /* somewhat like above, but use existing handle */ FILE * fdopen(handle, mode) int handle; char * mode; { int create_p = 0; /* not really used */ int append_p = 0; int flags; struct streamoid * s; if (isatty(handle)) flags = STR_TEXT_P | STR_INTERACTIVE_P; else flags = STR_TEXT_P | STR_BUFFERED_P; if (handle <= GEM_MAX_SYSTEM_HANDLE) /* special one? */ flags |= STR_NOCLOSE_P; /* don't close this handle at exit time */ flags = parse_open_mode(mode, flags, &create_p, &append_p); s = __make_stream(handle, flags, gem_method_selector, append_p); return((FILE * )s); } /* el disgusto. */ FILE * freopen(name, mode, s) char * name; char * mode; struct streamoid * s; { int new_handle; int create_p, append_p, flags; if (!(s->flags & STR_OPEN_P)) /* trying to fool us? */ return(NULL); #ifdef new_experimental_version flags = parse_open_mode(mode, STR_BUFFERED_P | STR_TEXT_P, &create_p, &append_p); #else flags = parse_open_mode(mode, s->flags & (STR_BUFFERED_P | STR_TEXT_P), &create_p, &append_p); #endif new_handle = open_internal(name, flags & STR_INPUT_P, flags & STR_OUTPUT_P, create_p, append_p); if (new_handle < -3) return(NULL); /* I think this is right; lose and leave stream unaltered if can't open */ s->gemdos_handle = new_handle; s->file_position = 0; if (s->flags & STR_BUFFERED_P) { #ifdef new_experimental_version if (!s->buffer) { s->buffer = (unsigned char * ) malloc(s->buffer_size = 8192); } #endif s->buffer_nbytes = 0; s->buffer_pos = 0; } s->flags = flags & ~(STR_AT_EOF_P | STR_NOCLOSE_P); #ifdef new_experimental_version gem_method_selector(s, flags); s->flags |= STR_OPEN_P; #endif return((FILE * )s); } fclose(s) struct streamoid * s; { /* temporary kludge til get unbuffered methods straightened out w/r/t freopen */ if ((s->flags & STR_BUFFERED_P) && (s->flags & STR_OUTPUT_P)) __force_output(s); method_call_0(s, METHOD_CLOSE); } fflush(s) struct streamoid * s; { if ((s->flags & STR_BUFFERED_P) && (s->flags & STR_OUTPUT_P)) __force_output(s); } int fgetc(s) struct streamoid * s; { int c = method_call_0(s, METHOD_TYI); if (c == EOF_VALUE) return(EOF); else return(c); } char * fgets(buf, nbytes, s) char * buf; int nbytes; struct streamoid * s; { int nbytes_read; *buf = '\0'; nbytes_read = method_call_2(s, METHOD_READL, buf, nbytes); if (nbytes_read > 0) return(buf); else return(NULL); } int fputc(c, s) int c; struct streamoid * s; { int res = method_call_1(s, METHOD_TYO, c); return(res < 0 ? res : c & 0xFF); } int fputs(str, s) char * str; struct streamoid * s; { method_call_1(s, METHOD_WRITEL, str); /* zzz what should this return? */ return(0); } long ftell(s) struct streamoid * s; { return(s->file_position); } long fseek(s, pos, mode) struct streamoid * s; long pos; int mode; { int result; result = method_call_2(s, METHOD_SEEK, pos, mode); if (result >= 0) return(0); else return(errno); } /* this is really not quite right, as it returns T for anything that's NOT seekable. that's as close as we can come to the broken eunuchs idea of what's not an interactive device. */ int isatty(handle) int handle; { int test_pos; int current_pos = Fseek(0, handle, L_INCR); if (current_pos != 0) /* not 0? */ return(0); /* we know it's not a file */ test_pos = Fseek(1, handle, L_INCR); /* try to seek ahead one */ if (test_pos == 0) /* couldn't seek forward? */ return(1); /* then it 'is a tty' */ if (test_pos == EBADARG) /* out of range? */ { Fseek(current_pos, handle, L_SET); /* put it back */ return(0); /* not a tty */ } errno = EBADF; /* can't figure it out */ return(0); }