Commit | Line | Data |
---|---|---|
394a1d25 C |
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 | } | |
272 |