1: /************************************************************************* 2: * This program is copyright (C) 1985, 1986 by Jonathan Payne. It is * 3: * provided to you without charge for use only on a licensed Unix * 4: * system. You may copy JOVE provided that this notice is included with * 5: * the copy. You may not sell copies of this program or versions * 6: * modified for use on microcomputer systems, unless the copies are * 7: * included with a Unix system distribution and the source is provided. * 8: *************************************************************************/ 9: 10: #include "jove.h" 11: #include "io.h" 12: #include "termcap.h" 13: #include <sys/stat.h> 14: #include <sys/file.h> 15: #include <errno.h> 16: 17: #define MAXFILES 20 /* good enough for my purposes */ 18: 19: static File _openfiles[MAXFILES] = {0}; 20: 21: static File * 22: f_alloc(name, flags, fd, buffer, buf_size) 23: char *buffer; 24: { 25: register File *fp; 26: register int i; 27: 28: for (fp = _openfiles, i = 0; i < MAXFILES; i++, fp++) 29: if (fp->f_flags == 0) 30: break; 31: if (i == MAXFILES) 32: complain("[Too many open files!]"); 33: fp->f_bufsize = buf_size; 34: fp->f_cnt = 0; 35: fp->f_fd = fd; 36: fp->f_flags = flags; 37: if (buffer == 0) { 38: buffer = emalloc(buf_size); 39: fp->f_flags |= F_MYBUF; 40: } 41: fp->f_base = fp->f_ptr = buffer; 42: fp->f_name = copystr(name); 43: 44: return fp; 45: } 46: 47: gc_openfiles() 48: { 49: register File *fp; 50: 51: for (fp = _openfiles; fp < &_openfiles[MAXFILES]; fp++) 52: if (fp->f_flags != 0 && (fp->f_flags & F_LOCK) == 0) 53: f_close(fp); 54: } 55: 56: File * 57: fd_open(name, flags, fd, buffer, bsize) 58: char *buffer; 59: { 60: return f_alloc(name, flags, fd, buffer, bsize); 61: } 62: 63: File * 64: f_open(name, flags, buffer, buf_size) 65: char *name, 66: *buffer; 67: { 68: register int fd; 69: int mode = F_MODE(flags); 70: 71: if (mode == F_READ) 72: fd = open(name, 0); 73: if (mode == F_APPEND) { 74: fd = open(name, 1); 75: if (fd == -1) 76: mode = F_WRITE; 77: else 78: (void) lseek(fd, (long) 0, 2); 79: } 80: if (mode == F_WRITE) 81: fd = creat(name, CreatMode); 82: if (fd == -1) 83: return NIL; 84: return f_alloc(name, flags, fd, buffer, buf_size); 85: } 86: 87: f_close(fp) 88: File *fp; 89: { 90: flush(fp); 91: #ifdef BSD4_2 92: if (fp->f_flags & (F_WRITE|F_APPEND)) 93: (void) fsync(fp->f_fd); 94: #endif 95: (void) close(fp->f_fd); 96: if (fp->f_flags & F_MYBUF) 97: free(fp->f_base); 98: free(fp->f_name); 99: fp->f_flags = 0; /* indicates that we're available */ 100: } 101: 102: filbuf(fp) 103: File *fp; 104: { 105: if (fp->f_flags & (F_EOF|F_ERR)) 106: return EOF; 107: fp->f_ptr = fp->f_base; 108: fp->f_cnt = read(fp->f_fd, fp->f_base, fp->f_bufsize); 109: if (fp->f_cnt == -1) { 110: printf("[Read error %d]", errno); 111: fp->f_flags |= F_ERR; 112: } 113: if (fp->f_cnt == 0) { 114: fp->f_flags |= F_EOF; 115: return EOF; 116: } 117: io_chars += fp->f_cnt; 118: return getc(fp); 119: } 120: 121: putstr(s) 122: register char *s; 123: { 124: register int c; 125: 126: while (c = *s++) 127: putchar(c); 128: } 129: 130: fputnchar(s, n, fp) 131: register char *s; 132: register int n; 133: register File *fp; 134: { 135: while (--n >= 0) 136: putc(*s++, fp); 137: } 138: 139: putnchar(s, n) 140: register char *s; 141: register int n; 142: { 143: fputnchar(s, n, stdout); 144: } 145: 146: flusho() 147: { 148: _flush(EOF, stdout); 149: } 150: 151: flush(fp) 152: File *fp; 153: { 154: _flush(EOF, fp); 155: } 156: 157: _flush(c, fp) 158: register File *fp; 159: { 160: register int n; 161: 162: if ((fp->f_flags & F_READ) || 163: ((fp->f_flags & F_STRING))) 164: return; 165: if (((n = (fp->f_ptr - fp->f_base)) > 0) && 166: (write(fp->f_fd, fp->f_base, n) != n) && 167: (fp != stdout)) 168: error("[I/O error(%d); file = %s, fd = %d]", 169: errno, fp->f_name, fp->f_fd); 170: 171: if (fp == stdout) 172: OkayAbort = YES; 173: fp->f_cnt = fp->f_bufsize; 174: fp->f_ptr = fp->f_base; 175: if (c != EOF) 176: putc(c, fp); 177: } 178: 179: f_gets(fp, buf, max) 180: register File *fp; 181: char *buf; 182: { 183: register char *cp = buf; 184: register int c; 185: char *endp = buf + max - 1; 186: 187: if (fp->f_flags & F_EOF) 188: return EOF; 189: while (((c = getc(fp)) != EOF) && (c != '\n')) { 190: if (c == NULL) 191: continue; /* sorry we don't read nulls */ 192: if (cp >= endp) { 193: add_mess(" [Line too long]"); 194: rbell(); 195: return EOF; 196: } 197: *cp++ = c; 198: } 199: *cp = '\0'; 200: if (c == EOF) { 201: if (cp != buf) 202: add_mess(" [Incomplete last line]"); 203: fp->f_flags |= F_EOF; 204: return EOF; 205: } 206: io_lines++; 207: return NIL; /* this means okay */ 208: } 209: 210: /* Deals with output to the terminal, setting up the amount of characters 211: to be buffered depending on the output baud rate. Why it's in a 212: separate file I don't know ... */ 213: 214: static char one_buf; 215: 216: int BufSize = 1; 217: 218: static File _stdout = {1, 1, 1, F_WRITE, &one_buf, &one_buf}; 219: File *stdout = &_stdout; 220: 221: /* put a string with padding */ 222: 223: tputc(c) 224: { 225: putchar(c); 226: } 227: 228: #undef putchar /* for files which forget to include io.h, 229: here's a real putchar procedure. */ 230: putchar(c) 231: { 232: putc(c, stdout); 233: } 234: 235: putpad(str, lines) 236: char *str; 237: { 238: if (str) 239: tputs(str, lines, tputc); 240: } 241: 242: /* Determine the number of characters to buffer at each baud rate. The 243: lower the number, the quicker the response when new input arrives. Of 244: course the lower the number, the more prone the program is to stop in 245: output. Decide what matters most to you. This sets BufSize to the right 246: number or chars, and initiaizes `stdout'. */ 247: 248: settout(ttbuf) 249: char *ttbuf; 250: { 251: static int speeds[] = { 252: 1, /* 0 */ 253: 1, /* 50 */ 254: 1, /* 75 */ 255: 1, /* 110 */ 256: 1, /* 134 */ 257: 1, /* 150 */ 258: 1, /* 200 */ 259: 2, /* 300 */ 260: 4, /* 600 */ 261: 8, /* 1200 */ 262: 16, /* 1800 */ 263: 32, /* 2400 */ 264: 128, /* 4800 */ 265: 256, /* 9600 */ 266: 512, /* EXTA */ 267: 512 /* EXT */ 268: }; 269: BufSize = min(512, (speeds[ospeed] * max(LI / 24, 1))); 270: stdout = fd_open("/dev/tty", F_WRITE|F_LOCK, 1, ttbuf, BufSize); 271: }