|
|
1.1 root 1: /*
2: * File: fsys.c
3: * Contents: close, exit, open, read, reads, stop, system, write, writes
4: */
5:
6: #include "../h/rt.h"
7:
8: /*
9: * close(f) - close file f.
10: */
11:
12: FncDcl(close,1)
13: {
14: register int i;
15:
16: /*
17: * f must be a file.
18: */
19: if (Arg1.dword != D_File)
20: runerr(105, &Arg1);
21:
22: /*
23: * If f has a buffer associated with it, "free" it.
24: */
25: for (i = 0; i < numbufs; i++) {
26: if (bufused[i] == BlkLoc(Arg1)->file.fd) {
27: bufused[i] = NULL;
28: break;
29: }
30: }
31:
32: /*
33: * Close f, using fclose or pclose as appropriate.
34: */
35: #ifndef MSDOS
36: if (BlkLoc(Arg1)->file.status & Fs_Pipe)
37: pclose(BlkLoc(Arg1)->file.fd);
38: else
39: #endif MSDOS
40: fclose(BlkLoc(Arg1)->file.fd);
41: BlkLoc(Arg1)->file.status = 0;
42:
43: /*
44: * Return the closed file.
45: */
46: Arg0 = Arg1;
47: Return;
48: }
49:
50:
51: /*
52: * exit(status) - exit process with specified status, defaults to 0.
53: */
54:
55: FncDcl(exit,1)
56: {
57: defshort(&Arg1, NormalExit);
58: c_exit((int)IntVal(Arg1));
59: }
60:
61:
62: /*
63: * open(s1,s2) - open file s1 with specification s2.
64: */
65: FncDcl(open,2)
66: {
67: register word slen;
68: register int i;
69: register char *s;
70: int status;
71: #ifndef MSDOS
72: char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen], mode[3];
73: #else MSDOS
74: char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen], mode[4];
75: char untranslated;
76: #endif MSDOS
77: FILE *f;
78: extern struct b_file *alcfile();
79: extern char *alcstr();
80: #ifndef MSDOS
81: extern FILE *fopen(), *popen();
82: #else MSDOS
83: extern FILE *fopen();
84: #endif MSDOS
85: /*
86: * s1 must be a string and a C string copy of it is also needed.
87: * Make it a string if it isn't one; make a C string if s1 is
88: * a string.
89: */
90: switch (cvstr(&Arg1, sbuf1)) {
91:
92: case Cvt:
93: strreq(StrLen(Arg1));
94: StrLoc(Arg1) = alcstr(StrLoc(Arg1), StrLen(Arg1));
95: break;
96:
97: case NoCvt:
98: qtos(&Arg1, sbuf1);
99: break;
100:
101: default:
102: runerr(103, &Arg1);
103: }
104: /*
105: * s2 defaults to "r".
106: */
107: defstr(&Arg2, sbuf2, &letr);
108:
109: blkreq((word)sizeof(struct b_file));
110: status = 0;
111: #ifdef MSDOS
112: untranslated = 0;
113: #endif MSDOS
114: /*
115: * Scan s2, setting appropriate bits in status. Produce a runerr
116: * if an unknown character is encountered.
117: */
118: s = StrLoc(Arg2);
119: slen = StrLen(Arg2);
120: for (i = 0; i < slen; i++) {
121: switch (*s++) {
122: case 'a': case 'A':
123: status |= Fs_Write|Fs_Append;
124: continue;
125: case 'b': case 'B':
126: status |= Fs_Read|Fs_Write;
127: continue;
128: case 'c': case 'C':
129: status |= Fs_Create|Fs_Write;
130: continue;
131: #ifndef MSDOS
132: case 'p': case 'P':
133: status |= Fs_Pipe;
134: continue;
135: #else MSDOS
136: case 't': case 'T': /* Add a translated (default) */
137: untranslated = 0;
138: continue;
139: case 'u': case 'U': /* Add a translated (default) */
140: untranslated = 1;
141: continue;
142: #endif MSDOS
143: case 'r': case 'R':
144: status |= Fs_Read;
145: continue;
146: case 'w': case 'W':
147: status |= Fs_Write;
148: continue;
149: default:
150: runerr(209, &Arg2);
151: }
152: }
153:
154: /*
155: * Construct a mode field for fopen/popen.
156: */
157: mode[0] = '\0';
158: mode[1] = '\0';
159: mode[2] = '\0';
160: #ifdef MSDOS
161: mode[3] = '\0';
162: #endif MSDOS
163: if ((status & (Fs_Read|Fs_Write)) == 0) /* default: read only */
164: status |= Fs_Read;
165: if (status & Fs_Create)
166: mode[0] = 'w';
167: else if (status & Fs_Append)
168: mode[0] = 'a';
169: else if (status & Fs_Read)
170: mode[0] = 'r';
171: else
172: mode[0] = 'w';
173: #ifndef MSDOS
174: if ((status & (Fs_Read|Fs_Write)) == (Fs_Read|Fs_Write))
175: mode[1] = '+';
176: #else MSDOS
177: if ((status & (Fs_Read|Fs_Write)) == (Fs_Read|Fs_Write)) {
178: mode[1] = '+';
179: mode[2] = untranslated ? 'b' : 't';
180: }
181: else mode[1] = untranslated ? 'b' : 't';
182: #endif MSDOS
183:
184: /*
185: * Open the file with fopen or popen.
186: */
187: #ifndef MSDOS
188: if (status & Fs_Pipe) {
189: if (status != (Fs_Read|Fs_Pipe) && status != (Fs_Write|Fs_Pipe))
190: runerr(209, &Arg2);
191: f = popen(sbuf1, mode);
192: }
193: else
194: #endif MSDOS
195: f = fopen(sbuf1, mode);
196: /*
197: * Fail if the file can't be opened.
198: */
199: if (f == NULL)
200: Fail;
201: /*
202: * If the file isn't a terminal and a buffer is available, assign
203: * it to the file.
204: */
205: #ifndef VMS
206: if (!isatty(fileno(f))) {
207: for (i = 0; i < numbufs; i++)
208: if (bufused[i] == NULL)
209: break;
210: if (i < numbufs) { /* Use buffer if any free. */
211: setbuf(f, bufs[i]);
212: bufused[i] = f;
213: }
214: else
215: setbuf(f, NULL);
216: }
217: else
218: setbuf(f, NULL);
219: #endif VMS
220: /*
221: * Return the resulting file value.
222: */
223: Arg0.dword = D_File;
224: BlkLoc(Arg0) = (union block *) alcfile(f, status, &Arg1);
225: Return;
226: }
227:
228:
229: /*
230: * read(f) - read line on file f.
231: */
232: FncDcl(read,1)
233: {
234: register word slen;
235: int status;
236: static char sbuf[MaxReadStr];
237: FILE *f;
238: extern char *alcstr();
239:
240: /*
241: * Default f to &input.
242: */
243: deffile(&Arg1, &input);
244: /*
245: * Get a pointer to the file and be sure that it's open for reading.
246: */
247: f = BlkLoc(Arg1)->file.fd;
248: status = BlkLoc(Arg1)->file.status;
249: if ((status & Fs_Read) == 0)
250: runerr(212, &Arg1);
251:
252: /*
253: * Use getstr to read a line from the file, failing if getstr
254: * encounters end of file.
255: */
256: if ((slen = getstr(sbuf,MaxReadStr,f)) < 0)
257: Fail;
258: /*
259: * Allocate the string read and make Arg0 a descriptor for it.
260: */
261: strreq(slen);
262: StrLen(Arg0) = slen;
263: StrLoc(Arg0) = alcstr(sbuf,slen);
264: Return;
265: }
266:
267:
268: /*
269: * reads(f,i) - read i characters on file f.
270: */
271: FncDcl(reads,2)
272: {
273: register int cnt;
274: int status;
275: FILE *f;
276:
277: /*
278: * f defaults to &input and i defaults to 1 (character).
279: */
280: deffile(&Arg1, &input);
281: defshort(&Arg2, 1);
282:
283: /*
284: * Get a pointer to the file and be sure that it's open for reading.
285: */
286: f = BlkLoc(Arg1)->file.fd;
287: status = BlkLoc(Arg1)->file.status;
288: if ((status & Fs_Read) == 0)
289: runerr(212, &Arg1);
290:
291: /*
292: * Be sure that a positive number of bytes is to be read.
293: */
294: if ((cnt = IntVal(Arg2)) <= 0)
295: runerr(205, &Arg2);
296:
297: /*
298: * Ensure that enough space for the string exists and read it directly
299: * into the string space. (By reading directly into the string space,
300: * no arbitrary restrictions are placed on the size of the string that
301: * can be read.) Make Arg0 a descriptor for the string and return it.
302: */
303: strreq((word)cnt);
304: if (strfree + cnt > strend)
305: syserr("string allocation botch");
306: StrLoc(Arg0) = strfree;
307: if ((cnt = fread(StrLoc(Arg0), sizeof(char), cnt, f)) <= 0)
308: Fail;
309: StrLen(Arg0) = cnt;
310: strfree += cnt;
311: Return;
312: }
313:
314:
315: /*
316: * stop(a,b,...) - write arguments (starting on error output) and stop.
317: */
318:
319: FncDclV(stop)
320: {
321: register word n;
322: char sbuf[MaxCvtLen];
323: struct descrip arg;
324: FILE *f;
325:
326: f = stderr;
327: /*
328: * Loop through arguments.
329: */
330:
331: for (n = 1; n <= nargs; n++) {
332: arg = Arg(n);
333: if (arg.dword == D_File) {
334: if (n > 1)
335: putc('\n', f);
336: if ((BlkLoc(arg)->file.status & Fs_Write) == 0)
337: runerr(213, &arg);
338: f = BlkLoc(arg)->file.fd;
339: }
340: else {
341: if (n == 1 && (k_output.status & Fs_Write) == 0)
342: runerr(213, NULL);
343: if (ChkNull(arg))
344: arg = emptystr;
345: if (cvstr(&arg, sbuf) == NULL)
346: runerr(109, &arg);
347: putstr(f, StrLoc(arg), StrLen(arg));
348: }
349: }
350:
351: putc('\n', f);
352: c_exit(ErrorExit);
353: }
354:
355:
356: /*
357: * system(s) - execute string s as a system command.
358: */
359:
360: FncDcl(system,1)
361: {
362: char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen];
363: #ifdef VMS
364: struct { long size; char *ptr; } descr;
365: int status;
366: #endif VMS
367:
368: /*
369: * s must be string and smaller than MaxCvtLen characters long.
370: */
371: if (cvstr(&Arg1, sbuf1) == NULL)
372: runerr(103, &Arg1);
373: if (StrLen(Arg1) >= MaxCvtLen)
374: runerr(210, &Arg1);
375: qtos(&Arg1, sbuf2);
376:
377: /*
378: * Pass the C string made by qtos to the UNIX system() function and
379: * return the exit code of the command as the result of system().
380: */
381: #ifndef VMS
382: Mkint((long)((system(sbuf2) >> 8) & 0377), &Arg0);
383: Return;
384: #else
385: descr.ptr = sbuf2; descr.size = StrLen(Arg1); status = 0;
386: status = lib$spawn(&descr,0,0,0,0,0, &status,0,0,0);
387: Mkint((long)status|ErrorExit, &Arg0);
388: Return;
389: #endif VMS
390: }
391:
392:
393: /*
394: * write(a,b,...) - write arguments.
395: */
396: FncDclV(write)
397: {
398: register word n;
399: char sbuf[MaxCvtLen];
400: struct descrip arg;
401: FILE *f;
402: extern char *alcstr();
403:
404: f = stdout;
405: arg = emptystr;
406:
407: /*
408: * Loop through the arguments.
409: */
410: for (n = 1; n <= nargs; n++) {
411: arg = Arg(n);
412: if (arg.dword == D_File) {/* Current argument is a file */
413: /*
414: * If this isn't the first argument, output a newline to the current
415: * file and flush it.
416: */
417: if (n > 1) {
418: putc('\n', f);
419: fflush(f);
420: }
421: /*
422: * Switch the current file to the file named by the current argument
423: * providing it is a file. arg is made to be a empty string to
424: * avoid a special case.
425: */
426: if ((BlkLoc(arg)->file.status & Fs_Write) == 0)
427: runerr(213, &arg);
428: f = BlkLoc(arg)->file.fd;
429: arg = emptystr;
430: }
431: else { /* Current argument is a string */
432: /*
433: * On first argument, check to be sure that &output is open
434: * for output.
435: */
436: if (n == 1 && (k_output.status & Fs_Write) == 0)
437: runerr(213, NULL);
438: /*
439: * Convert the argument to a string, defaulting to a empty string.
440: */
441: if (ChkNull(arg))
442: arg = emptystr;
443: if (cvstr(&arg, sbuf) == NULL)
444: runerr(109, &arg);
445: /*
446: * Output the string.
447: */
448: putstr(f, StrLoc(arg), StrLen(arg));
449: }
450: }
451: /*
452: * Append a newline to the file and flush it.
453: */
454: putc('\n', f);
455: fflush(f);
456: /*
457: * If the beginning of the last string output lies in sbuf,
458: * allocate it as a real string. Note that some of the string
459: * conversions don't always leave the converted string at the
460: * start of the conversion buffer, hence the range check.
461: */
462: if (StrLoc(arg) >= sbuf && StrLoc(arg) < sbuf + MaxCvtLen) {
463: strreq(StrLen(arg));
464: StrLoc(arg) = alcstr(StrLoc(arg), StrLen(arg));
465: }
466: /*
467: * Return the string corresponding to the last argument.
468: */
469: Arg(0) = arg;
470: Return;
471: }
472:
473:
474: /*
475: * writes(a,b,...) - write arguments without newline terminator.
476: */
477:
478: FncDclV(writes)
479: {
480: register word n;
481: char sbuf[MaxCvtLen];
482: struct descrip arg;
483: FILE *f;
484: extern char *alcstr();
485:
486: f = stdout;
487: arg = emptystr;
488:
489: /*
490: * Loop through the arguments.
491: */
492: for (n = 1; n <= nargs; n++) {
493: arg = Arg(n);
494: if (arg.dword == D_File) {/* Current argument is a file */
495: /*
496: * Switch the current file to the file named by the current argument
497: * providing it is a file. arg is made to be a empty string to
498: * avoid a special case.
499: */
500: if ((BlkLoc(arg)->file.status & Fs_Write) == 0)
501: runerr(213, &arg);
502: f = BlkLoc(arg)->file.fd;
503: arg = emptystr;
504: }
505: else { /* Current argument is a string */
506: /*
507: * On first argument, check to be sure that &output is open
508: * for output.
509: */
510: if (n == 1 && (k_output.status & Fs_Write) == 0)
511: runerr(213, NULL);
512: /*
513: * Convert the argument to a string, defaulting to a empty string.
514: */
515: if (ChkNull(arg))
516: arg = emptystr;
517: if (cvstr(&arg, sbuf) == NULL)
518: runerr(109, &arg);
519: /*
520: * Output the string and flush the file.
521: */
522: putstr(f, StrLoc(arg), StrLen(arg));
523: fflush(f);
524: }
525: }
526: /*
527: * If the beginning of the last string output lies in sbuf,
528: * allocate it as a real string. Note that some of the string
529: * conversions don't always leave the converted string at the
530: * start of the conversion buffer, hence the range check.
531: */
532: if (StrLoc(arg) >= sbuf && StrLoc(arg) < sbuf + MaxCvtLen) {
533: strreq(StrLen(arg));
534: StrLoc(arg) = alcstr(StrLoc(arg), StrLen(arg));
535: }
536: /*
537: * Return the string corresponding to the last argument.
538: */
539: Arg(0) = arg;
540: Return;
541: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.