|
|
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.