|
|
1.1 ! root 1: /*************************************************************************** ! 2: * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * ! 3: * is provided to you without charge, and with no warranty. You may give * ! 4: * away copies of JOVE, including sources, provided that this notice is * ! 5: * included in all the files. * ! 6: ***************************************************************************/ ! 7: ! 8: #include "jove.h" ! 9: #include "io.h" ! 10: #include "termcap.h" ! 11: ! 12: #ifdef IPROCS ! 13: # include <signal.h> ! 14: #endif ! 15: ! 16: #ifdef MAC ! 17: # include "mac.h" ! 18: #else ! 19: # include <sys/stat.h> ! 20: #endif ! 21: ! 22: #ifdef UNIX ! 23: #include <sys/file.h> ! 24: #ifdef YP_PASSWD ! 25: #include <rpcsvc/ypclnt.h> ! 26: #endif ! 27: #endif ! 28: ! 29: #ifdef MSDOS ! 30: #include <fcntl.h> ! 31: #include <io.h> ! 32: #ifdef CHDIR ! 33: #include <direct.h> ! 34: #include <dos.h> ! 35: #endif ! 36: #endif /* MSDOS */ ! 37: #include <errno.h> ! 38: ! 39: #ifdef MAC ! 40: # undef private ! 41: # define private ! 42: #endif ! 43: ! 44: #ifdef LINT_ARGS ! 45: private struct block ! 46: * b_unlink(struct block *), ! 47: * lookup(short); ! 48: ! 49: private char ! 50: * dbackup(char *, char *, char), ! 51: #if defined(MSDOS) && defined(CHDIR) ! 52: * fixpath(char *), ! 53: #endif ! 54: * getblock(disk_line, int); ! 55: ! 56: private void ! 57: #if defined(MSDOS) && defined(CHDIR) ! 58: abspath(char *, char *), ! 59: #endif ! 60: fake_blkio(struct block *, int (*)()), ! 61: LRUunlink(struct block *), ! 62: real_blkio(struct block *, int (*)()); ! 63: ! 64: private int ! 65: #if defined(MSDOS) && defined(CHDIR) ! 66: Dchdir(char *), ! 67: #endif ! 68: dfollow(char *, char *); ! 69: ! 70: #else ! 71: private struct block ! 72: * b_unlink(), ! 73: * lookup(); ! 74: ! 75: private char ! 76: * dbackup(), ! 77: #if defined(MSDOS) && defined(CHDIR) ! 78: * fixpath(), ! 79: #endif ! 80: * getblock(); ! 81: ! 82: private void ! 83: #if defined(MSDOS) && defined(CHDIR) ! 84: abspath(), ! 85: #endif ! 86: fake_blkio(), ! 87: LRUunlink(), ! 88: real_blkio(); ! 89: ! 90: private int ! 91: #if defined(MSDOS) && defined(CHDIR) ! 92: Dchdir(), ! 93: #endif ! 94: dfollow(); ! 95: #endif /* LINT_ARGS */ ! 96: ! 97: #ifdef MAC ! 98: # undef private ! 99: # define private static ! 100: #endif ! 101: ! 102: ! 103: #ifndef W_OK ! 104: # define W_OK 2 ! 105: # define F_OK 0 ! 106: #endif ! 107: ! 108: long io_chars; /* number of chars in this open_file */ ! 109: int io_lines; /* number of lines in this open_file */ ! 110: ! 111: #if defined(VMUNIX)||defined(MSDOS) ! 112: char iobuff[LBSIZE], ! 113: genbuf[LBSIZE], ! 114: linebuf[LBSIZE]; ! 115: #else ! 116: char *iobuff, ! 117: *genbuf, ! 118: *linebuf; ! 119: #endif ! 120: ! 121: #ifdef BACKUPFILES ! 122: int BkupOnWrite = 0; ! 123: #endif ! 124: ! 125: void ! 126: close_file(fp) ! 127: File *fp; ! 128: { ! 129: if (fp) { ! 130: if (fp->f_flags & F_TELLALL) ! 131: add_mess(" %d lines, %D characters.", ! 132: io_lines, ! 133: io_chars); ! 134: f_close(fp); ! 135: } ! 136: } ! 137: ! 138: /* Write the region from line1/char1 to line2/char2 to FP. This ! 139: never CLOSES the file since we don't know if we want to. */ ! 140: ! 141: int EndWNewline = 1; ! 142: ! 143: void ! 144: putreg(fp, line1, char1, line2, char2, makesure) ! 145: register File *fp; ! 146: Line *line1, ! 147: *line2; ! 148: { ! 149: register int c; ! 150: register char *lp; ! 151: ! 152: if (makesure) ! 153: (void) fixorder(&line1, &char1, &line2, &char2); ! 154: while (line1 != line2->l_next) { ! 155: lp = lcontents(line1) + char1; ! 156: if (line1 == line2) { ! 157: fputnchar(lp, (char2 - char1), fp); ! 158: io_chars += (char2 - char1); ! 159: } else while (c = *lp++) { ! 160: putc(c, fp); ! 161: io_chars += 1; ! 162: } ! 163: if (line1 != line2) { ! 164: io_lines += 1; ! 165: io_chars += 1; ! 166: #ifdef MSDOS ! 167: putc('\r', fp); ! 168: #endif /* MSDOS */ ! 169: putc('\n', fp); ! 170: } ! 171: line1 = line1->l_next; ! 172: char1 = 0; ! 173: } ! 174: flush(fp); ! 175: } ! 176: ! 177: void ! 178: read_file(file, is_insert) ! 179: char *file; ! 180: { ! 181: Bufpos save; ! 182: File *fp; ! 183: if (!is_insert) { ! 184: curbuf->b_ntbf = 0; ! 185: set_ino(curbuf); ! 186: } ! 187: fp = open_file(file, iobuff, F_READ, !COMPLAIN, !QUIET); ! 188: if (fp == NIL) { ! 189: if (!is_insert && errno == ENOENT) ! 190: s_mess("(new file)"); ! 191: else ! 192: s_mess(IOerr("open", file)); ! 193: return; ! 194: } ! 195: DOTsave(&save); ! 196: dofread(fp); ! 197: if (is_insert && io_chars > 0) { ! 198: modify(); ! 199: set_mark(); ! 200: } ! 201: SetDot(&save); ! 202: getDOT(); ! 203: close_file(fp); ! 204: } ! 205: ! 206: void ! 207: dofread(fp) ! 208: register File *fp; ! 209: { ! 210: char end[LBSIZE]; ! 211: int xeof = 0; ! 212: Line *savel = curline; ! 213: int savec = curchar; ! 214: extern disk_line f_getputl(); ! 215: ! 216: strcpy(end, linebuf + curchar); ! 217: xeof = f_gets(fp, linebuf + curchar, LBSIZE - curchar); ! 218: SavLine(curline, linebuf); ! 219: if (!xeof) do { ! 220: curline = listput(curbuf, curline); ! 221: xeof = f_getputl(curline, fp); ! 222: } while (!xeof); ! 223: getDOT(); ! 224: linecopy(linebuf, (curchar = strlen(linebuf)), end); ! 225: SavLine(curline, linebuf); ! 226: IFixMarks(savel, savec, curline, curchar); ! 227: } ! 228: ! 229: void ! 230: SaveFile() ! 231: { ! 232: if (IsModified(curbuf)) { ! 233: if (curbuf->b_fname == 0) ! 234: WriteFile(); ! 235: else { ! 236: filemunge(curbuf->b_fname); ! 237: #ifndef MAC ! 238: #ifndef MSDOS /* not sure - kg - */ ! 239: chk_mtime(curbuf, curbuf->b_fname, "save"); ! 240: #endif /* MSDOS */ ! 241: #endif /* MAC */ ! 242: file_write(curbuf->b_fname, 0); ! 243: unmodify(); ! 244: } ! 245: } else ! 246: message("No changes need to be written."); ! 247: } ! 248: ! 249: char *HomeDir; /* home directory */ ! 250: int HomeLen = -1; /* length of home directory string */ ! 251: ! 252: #ifndef CHDIR ! 253: ! 254: char * ! 255: pr_name(fname, okay_home) ! 256: char *fname; ! 257: { ! 258: if (fname == 0) ! 259: return 0; ! 260: ! 261: if (okay_home == YES && strncmp(fname, HomeDir, HomeLen) == 0) { ! 262: static char name_buf[100]; ! 263: ! 264: sprintf(name_buf, "~%s", fname + HomeLen); ! 265: return name_buf; ! 266: } ! 267: ! 268: return fname; ! 269: } ! 270: ! 271: #else ! 272: ! 273: #define NDIRS 5 ! 274: ! 275: private char *DirStack[NDIRS] = {0}; ! 276: private int DirSP = 0; /* Directory stack pointer */ ! 277: #define PWD (DirStack[DirSP]) ! 278: ! 279: char * ! 280: pwd() ! 281: { ! 282: return PWD; ! 283: } ! 284: ! 285: char * ! 286: pr_name(fname, okay_home) ! 287: char *fname; ! 288: { ! 289: int n; ! 290: ! 291: if (fname == 0) ! 292: return 0; ! 293: n = numcomp(fname, PWD); ! 294: ! 295: if ((PWD[n] == 0) && /* Matched to end of PWD */ ! 296: (fname[n] == '/')) ! 297: return fname + n + 1; ! 298: ! 299: if (okay_home == YES && strcmp(HomeDir, "/") != 0 && strncmp(fname, HomeDir, HomeLen) == 0) { ! 300: static char name_buf[100]; ! 301: ! 302: sprintf(name_buf, "~%s", fname + HomeLen); ! 303: return name_buf; ! 304: } ! 305: ! 306: return fname; /* return entire path name */ ! 307: } ! 308: ! 309: extern unsigned int fmask; ! 310: ! 311: Chdir() ! 312: { ! 313: char dirbuf[FILESIZE]; ! 314: ! 315: #ifdef MSDOS ! 316: fmask = 0x10; ! 317: #endif ! 318: (void) ask_file((char *) 0, PWD, dirbuf); ! 319: #ifdef MSDOS ! 320: fmask = 0x13; ! 321: if (Dchdir(dirbuf) == -1) ! 322: #else ! 323: if (chdir(dirbuf) == -1) ! 324: #endif ! 325: { ! 326: s_mess("cd: cannot change into %s.", dirbuf); ! 327: return; ! 328: } ! 329: UpdModLine = YES; ! 330: setCWD(dirbuf); ! 331: prCWD(); ! 332: #ifdef MAC ! 333: Bufchange++; ! 334: #endif ! 335: } ! 336: ! 337: #ifdef UNIX ! 338: #ifndef JOB_CONTROL ! 339: char * ! 340: getwd(buffer) ! 341: char *buffer; ! 342: { ! 343: Buffer *old = curbuf; ! 344: char *ret_val; ! 345: ! 346: SetBuf(do_select((Window *) 0, "pwd-output")); ! 347: curbuf->b_type = B_PROCESS; ! 348: (void) UnixToBuf("pwd-output", NO, 0, YES, "/bin/pwd", (char *) 0); ! 349: ToFirst(); ! 350: strcpy(buffer, linebuf); ! 351: SetBuf(old); ! 352: return buffer; ! 353: } ! 354: #endif ! 355: #endif /* UNIX */ ! 356: ! 357: setCWD(d) ! 358: char *d; ! 359: { ! 360: if (PWD == 0) ! 361: PWD = malloc((unsigned) strlen(d) + 1); ! 362: else { ! 363: extern char *ralloc(); ! 364: ! 365: PWD = ralloc(PWD, strlen(d) + 1); ! 366: } ! 367: strcpy(PWD, d); ! 368: } ! 369: ! 370: getCWD() ! 371: { ! 372: char *cwd; ! 373: char pathname[FILESIZE]; ! 374: #if defined(UNIX) && defined(JOB_CONTROL) ! 375: extern char *getwd(); ! 376: #endif ! 377: #if defined(MSDOS) ! 378: extern char *getcwd(); ! 379: #endif ! 380: ! 381: #ifndef MSDOS ! 382: cwd = getenv("CWD"); ! 383: if (cwd == 0) ! 384: cwd = getenv("PWD"); ! 385: if (cwd == 0) ! 386: cwd = getwd(pathname); ! 387: #else /* MSDOS */ ! 388: cwd = fixpath(getcwd(pathname, FILESIZE)); ! 389: #endif /* MSDOS */ ! 390: ! 391: setCWD(cwd); ! 392: } ! 393: ! 394: prDIRS() ! 395: { ! 396: register int i; ! 397: ! 398: s_mess(": %f "); ! 399: for (i = DirSP; i >= 0; i--) ! 400: add_mess("%s ", pr_name(DirStack[i], YES)); ! 401: } ! 402: ! 403: prCWD() ! 404: { ! 405: s_mess(": %f => \"%s\"", PWD); ! 406: } ! 407: ! 408: Pushd() ! 409: { ! 410: char *newdir, ! 411: dirbuf[FILESIZE]; ! 412: ! 413: #ifdef MSDOS ! 414: fmask = 0x10; ! 415: #endif ! 416: newdir = ask_file((char *) 0, NullStr, dirbuf); ! 417: #ifdef MSDOS ! 418: fmask = 0x13; ! 419: #endif ! 420: UpdModLine = YES; ! 421: if (*newdir == 0) { /* Wants to swap top two entries */ ! 422: char *old_top; ! 423: ! 424: if (DirSP == 0) ! 425: complain("pushd: no other directory."); ! 426: old_top = PWD; ! 427: DirStack[DirSP] = DirStack[DirSP - 1]; ! 428: DirStack[DirSP - 1] = old_top; ! 429: #ifdef MSDOS ! 430: (void) Dchdir(PWD); ! 431: #else ! 432: (void) chdir(PWD); ! 433: #endif ! 434: } else { ! 435: #ifdef MSDOS ! 436: if (Dchdir(dirbuf) == -1) { ! 437: #else ! 438: if (chdir(dirbuf) == -1) { ! 439: #endif ! 440: s_mess("pushd: cannot change into %s.", dirbuf); ! 441: return; ! 442: } ! 443: ! 444: if (DirSP + 1 >= NDIRS) ! 445: complain("pushd: full stack; max of %d pushes.", NDIRS); ! 446: DirSP += 1; ! 447: setCWD(dirbuf); ! 448: } ! 449: prDIRS(); ! 450: } ! 451: ! 452: Popd() ! 453: { ! 454: if (DirSP == 0) ! 455: complain("popd: directory stack is empty."); ! 456: UpdModLine = YES; ! 457: free(PWD); ! 458: PWD = 0; ! 459: DirSP -= 1; ! 460: #ifdef MSDOS ! 461: (void) Dchdir(PWD); /* If this doesn't work, we's in deep shit. */ ! 462: #else ! 463: (void) chdir(PWD); /* If this doesn't work, we's in deep shit. */ ! 464: #endif ! 465: prDIRS(); ! 466: } ! 467: ! 468: private char * ! 469: dbackup(base, offset, c) ! 470: register char *base, ! 471: *offset, ! 472: c; ! 473: { ! 474: while (offset > base && *--offset != c) ! 475: ; ! 476: return offset; ! 477: } ! 478: ! 479: private ! 480: dfollow(file, into) ! 481: char *file, ! 482: *into; ! 483: { ! 484: char *dp, ! 485: #ifdef MSDOS ! 486: filefix[FILESIZE], ! 487: #endif ! 488: *sp; ! 489: ! 490: #ifndef MSDOS ! 491: if (*file == '/') { /* Absolute pathname */ ! 492: strcpy(into, "/"); ! 493: file += 1; ! 494: } else ! 495: strcpy(into, PWD); ! 496: #else ! 497: abspath(file, filefix); /* convert to absolute pathname */ ! 498: strcpy(into, filefix); /* and forget about drives */ ! 499: into[3] = 0; ! 500: into = &(into[2]); ! 501: file = &(filefix[3]); ! 502: #endif ! 503: dp = into + strlen(into); ! 504: ! 505: sp = file; ! 506: do { ! 507: if (*file == 0) ! 508: break; ! 509: if (sp = index(file, '/')) ! 510: *sp = 0; ! 511: if (strcmp(file, ".") == 0) ! 512: ; /* So it will get to the end of the loop */ ! 513: else if (strcmp(file, "..") == 0) { ! 514: *(dp = dbackup(into, dp, '/')) = 0; ! 515: if (dp == into) ! 516: strcpy(into, "/"), dp = into + 1; ! 517: } else { ! 518: if (into[strlen(into) - 1] != '/') ! 519: (void) strcat(into, "/"), dp += 1; ! 520: (void) strcat(into, file); ! 521: dp += strlen(file); /* stay at the end */ ! 522: } ! 523: file = sp + 1; ! 524: } while (sp != 0); ! 525: } ! 526: ! 527: #endif /* CHDIR */ ! 528: ! 529: #ifdef UNIX ! 530: ! 531: #ifdef !NOGETPWENT ! 532: ! 533: #include <pwd.h> ! 534: private ! 535: get_hdir(user, buf) ! 536: register char *user, ! 537: *buf; ! 538: { ! 539: register struct passwd *pw; ! 540: ! 541: setpwent(); ! 542: while ((pw = getpwent()) != (struct passwd *)NULL) ! 543: if (strcmp(pw->pw_name, user) == 0) { ! 544: strncpy(buf, pw->pw_dir, FILESIZE); ! 545: buf[FILESIZE-1] = '\0'; ! 546: endpwent(); ! 547: return; ! 548: } ! 549: endpwent(); ! 550: complain("[unknown user: %s]", user); ! 551: } ! 552: ! 553: #else /* NOGETPWENT */ ! 554: ! 555: private ! 556: get_hdir(user, buf) ! 557: register char *user, ! 558: *buf; ! 559: { ! 560: char fbuf[LBSIZE], ! 561: pattern[100]; ! 562: register int u_len; ! 563: File *fp; ! 564: ! 565: u_len = strlen(user); ! 566: fp = open_file("/etc/passwd", fbuf, F_READ, COMPLAIN, QUIET); ! 567: sprintf(pattern, "%s:[^:]*:[^:]*:[^:]*:[^:]*:\\([^:]*\\):", user); ! 568: while (f_gets(fp, genbuf, LBSIZE) != EOF) ! 569: if ((strncmp(genbuf, user, u_len) == 0) && ! 570: (LookingAt(pattern, genbuf, 0))) { ! 571: putmatch(1, buf, FILESIZE); ! 572: close_file(fp); ! 573: return; ! 574: } ! 575: f_close(fp); ! 576: complain("[unknown user: %s]", user); ! 577: } ! 578: ! 579: #endif /* NOGETPWENT */ ! 580: #endif /* UNIX */ ! 581: ! 582: void ! 583: PathParse(name, intobuf) ! 584: char *name, ! 585: *intobuf; ! 586: { ! 587: char localbuf[FILESIZE]; ! 588: ! 589: intobuf[0] = localbuf[0] = '\0'; ! 590: if (*name == '\0') ! 591: return; ! 592: if (*name == '~') { ! 593: if (name[1] == '/' || name[1] == '\0') { ! 594: strcpy(localbuf, HomeDir); ! 595: name += 1; ! 596: #if !(defined(MSDOS) || defined(MAC)) /* may add for mac in future */ ! 597: } else { ! 598: char *uendp = index(name, '/'), ! 599: unamebuf[30]; ! 600: ! 601: if (uendp == 0) ! 602: uendp = name + strlen(name); ! 603: name = name + 1; ! 604: null_ncpy(unamebuf, name, uendp - name); ! 605: get_hdir(unamebuf, localbuf); ! 606: name = uendp; ! 607: #endif ! 608: } ! 609: } ! 610: #ifndef MSDOS ! 611: else if (*name == '\\') ! 612: name += 1; ! 613: #endif /* MSDOS */ ! 614: (void) strcat(localbuf, name); ! 615: #ifdef CHDIR ! 616: dfollow(localbuf, intobuf); ! 617: #else ! 618: strcpy(intobuf, localbuf); ! 619: #endif ! 620: } ! 621: ! 622: void ! 623: filemunge(newname) ! 624: char *newname; ! 625: { ! 626: struct stat stbuf; ! 627: ! 628: if (newname == 0) ! 629: return; ! 630: if (stat(newname, &stbuf)) ! 631: return; ! 632: #ifndef MSDOS ! 633: if (((stbuf.st_dev != curbuf->b_dev) || ! 634: (stbuf.st_ino != curbuf->b_ino)) && ! 635: #else /* MSDOS */ ! 636: if ( /* (stbuf.st_ino != curbuf->b_ino) && */ ! 637: #endif /* MSDOS */ ! 638: #ifndef MAC ! 639: ((stbuf.st_mode & S_IFMT) != S_IFCHR) && ! 640: #endif ! 641: (strcmp(newname, curbuf->b_fname) != 0)) { ! 642: rbell(); ! 643: confirm("\"%s\" already exists; overwrite it? ", newname); ! 644: } ! 645: } ! 646: ! 647: void ! 648: WrtReg() ! 649: { ! 650: DoWriteReg(NO); ! 651: } ! 652: ! 653: void ! 654: AppReg() ! 655: { ! 656: DoWriteReg(YES); ! 657: } ! 658: ! 659: int CreatMode = DFLT_MODE; ! 660: ! 661: void ! 662: DoWriteReg(app) ! 663: { ! 664: char fnamebuf[FILESIZE], ! 665: *fname; ! 666: Mark *mp = CurMark(); ! 667: File *fp; ! 668: ! 669: /* Won't get here if there isn't a Mark */ ! 670: fname = ask_file((char *) 0, (char *) 0, fnamebuf); ! 671: ! 672: #ifdef BACKUPFILES ! 673: if (app == NO) { ! 674: filemunge(fname); ! 675: ! 676: if (BkupOnWrite) ! 677: file_backup(fname); ! 678: } ! 679: #else ! 680: if (!app) ! 681: filemunge(fname); ! 682: #endif ! 683: ! 684: fp = open_file(fname, iobuff, app ? F_APPEND : F_WRITE, COMPLAIN, !QUIET); ! 685: putreg(fp, mp->m_line, mp->m_char, curline, curchar, YES); ! 686: close_file(fp); ! 687: } ! 688: ! 689: int OkayBadChars = 0; ! 690: ! 691: void ! 692: WriteFile() ! 693: { ! 694: char *fname, ! 695: fnamebuf[FILESIZE]; ! 696: #ifdef MAC ! 697: if (Macmode) { ! 698: if(!(fname = pfile(fnamebuf))) return; ! 699: } ! 700: else ! 701: #endif /* MAC */ ! 702: ! 703: fname = ask_file((char *) 0, curbuf->b_fname, fnamebuf); ! 704: /* Don't allow bad characters when creating new files. */ ! 705: if (!OkayBadChars && strcmp(curbuf->b_fname, fnamebuf) != 0) { ! 706: #ifdef UNIX ! 707: static char *badchars = "!$^&*()~`{}\"'\\|<>? "; ! 708: #endif /* UNIX */ ! 709: #ifdef MSDOS ! 710: static char *badchars = "*|<>? "; ! 711: #endif /* MSDOS */ ! 712: #ifdef MAC ! 713: static char *badchars = ":"; ! 714: #endif /* MAC */ ! 715: register char *cp = fnamebuf; ! 716: register int c; ! 717: ! 718: while (c = *cp++ & CHARMASK) /* avoid sign extension... */ ! 719: if (c < ' ' || c == '\177' || index(badchars, c)) ! 720: complain("'%p': bad character in filename.", c); ! 721: } ! 722: ! 723: #ifndef MAC ! 724: #ifndef MSDOS ! 725: chk_mtime(curbuf, fname, "write"); ! 726: #endif /* MSDOS */ ! 727: #endif /* MAC */ ! 728: filemunge(fname); ! 729: curbuf->b_type = B_FILE; /* in case it wasn't before */ ! 730: setfname(curbuf, fname); ! 731: file_write(fname, 0); ! 732: unmodify(); ! 733: } ! 734: ! 735: /* Open file FNAME supplying the buffer IO routine with buffer BUF. ! 736: HOW is F_READ, F_WRITE or F_APPEND. IFBAD == COMPLAIN means that ! 737: if we fail at opening the file, call complain. LOUDNESS says ! 738: whether or not to print the "reading ..." message on the message ! 739: line. ! 740: ! 741: NOTE: This opens the pr_name(fname, NO) of fname. That is, FNAME ! 742: is usually an entire pathname, which can be slow when the ! 743: pathname is long and there are lots of symbolic links along ! 744: the way (which has become very common in my experience). So, ! 745: this speeds up opens file names in the local directory. It ! 746: will not speed up things like "../scm/foo.scm" simple because ! 747: by the time we get here that's already been expanded to an ! 748: absolute pathname. But this is a start. ! 749: */ ! 750: ! 751: File * ! 752: open_file(fname, buf, how, ifbad, loudness) ! 753: register char *fname; ! 754: char *buf; ! 755: register int how; ! 756: { ! 757: register File *fp; ! 758: ! 759: io_chars = 0; ! 760: io_lines = 0; ! 761: ! 762: fp = f_open(pr_name(fname, NO), how, buf, LBSIZE); ! 763: if (fp == NIL) { ! 764: message(IOerr((how == F_READ) ? "open" : "create", fname)); ! 765: if (ifbad == COMPLAIN) ! 766: complain((char *) 0); ! 767: } else { ! 768: int readonly = FALSE; ! 769: #ifndef MAC ! 770: if (access(pr_name(fname, NO), W_OK) == -1 && errno != ENOENT) ! 771: readonly = TRUE; ! 772: #endif ! 773: if (loudness != QUIET) { ! 774: fp->f_flags |= F_TELLALL; ! 775: f_mess("\"%s\"%s", pr_name(fname, YES), ! 776: readonly ? " [Read only]" : NullStr); ! 777: } ! 778: } ! 779: return fp; ! 780: } ! 781: ! 782: #ifndef MSDOS ! 783: /* Check to see if the file has been modified since it was ! 784: last written. If so, make sure they know what they're ! 785: doing. ! 786: ! 787: I hate to use another stat(), but to use confirm we gotta ! 788: do this before we open the file. ! 789: ! 790: NOTE: This stats FNAME after converting it to a path-relative ! 791: name. I can't see why this would cause a problem ... ! 792: */ ! 793: ! 794: chk_mtime(thisbuf, fname, how) ! 795: Buffer *thisbuf; ! 796: char *fname, ! 797: *how; ! 798: { ! 799: struct stat stbuf; ! 800: Buffer *b; ! 801: char *mesg = "Shall I go ahead and %s anyway? "; ! 802: ! 803: if ((thisbuf->b_mtime != 0) && /* if we care ... */ ! 804: (b = file_exists(fname)) && /* we already have this file */ ! 805: (b == thisbuf) && /* and it's the current buffer */ ! 806: (stat(pr_name(fname, NO), &stbuf) != -1) && /* and we can stat it */ ! 807: (stbuf.st_mtime != b->b_mtime)) { /* and there's trouble. */ ! 808: rbell(); ! 809: redisplay(); /* Ring that bell! */ ! 810: TOstart("Warning", TRUE); ! 811: Typeout("\"%s\" now saved on disk is not what you last", pr_name(fname, YES)); ! 812: Typeout("visited or saved. Probably someone else is editing"); ! 813: Typeout("your file at the same time."); ! 814: if (how) { ! 815: Typeout(""); ! 816: Typeout("Type \"y\" if I should %s, anyway.", how); ! 817: f_mess(mesg, how); ! 818: } ! 819: TOstop(); ! 820: if (how) ! 821: confirm(mesg, how); ! 822: } ! 823: } ! 824: ! 825: #endif /* MSDOS */ ! 826: ! 827: void ! 828: file_write(fname, app) ! 829: char *fname; ! 830: { ! 831: File *fp; ! 832: ! 833: #ifdef BACKUPFILES ! 834: if (!app && BkupOnWrite) ! 835: file_backup(fname); ! 836: #endif ! 837: ! 838: fp = open_file(fname, iobuff, app ? F_APPEND : F_WRITE, COMPLAIN, !QUIET); ! 839: ! 840: if (EndWNewline) { /* Make sure file ends with a newLine */ ! 841: Bufpos save; ! 842: ! 843: DOTsave(&save); ! 844: ToLast(); ! 845: if (length(curline)) /* Not a blank Line */ ! 846: LineInsert(1); ! 847: SetDot(&save); ! 848: } ! 849: putreg(fp, curbuf->b_first, 0, curbuf->b_last, length(curbuf->b_last), NO); ! 850: set_ino(curbuf); ! 851: close_file(fp); ! 852: } ! 853: ! 854: void ! 855: ReadFile() ! 856: { ! 857: Buffer *bp; ! 858: char *fname, ! 859: fnamebuf[FILESIZE]; ! 860: int lineno; ! 861: ! 862: #ifdef MAC ! 863: if(Macmode) { ! 864: if(!(fname = gfile(fnamebuf))) return; ! 865: } ! 866: else ! 867: #endif /* MAC */ ! 868: fname = ask_file((char *) 0, curbuf->b_fname, fnamebuf); ! 869: #if !(defined(MSDOS) || defined(MAC)) ! 870: chk_mtime(curbuf, fname, "read"); ! 871: #endif /* MSDOS || MAC */ ! 872: ! 873: if (IsModified(curbuf)) { ! 874: char *y_or_n; ! 875: int c; ! 876: ! 877: for (;;) { ! 878: rbell(); ! 879: y_or_n = ask(NullStr, "Shall I make your changes to \"%s\" permanent? ", curbuf->b_name); ! 880: c = CharUpcase(*y_or_n); ! 881: if (c == 'Y' || c == 'N') ! 882: break; ! 883: } ! 884: if (c == 'Y') ! 885: SaveFile(); ! 886: } ! 887: ! 888: if ((bp = file_exists(fnamebuf)) && ! 889: (bp == curbuf)) ! 890: lineno = pnt_line() - 1; ! 891: else ! 892: lineno = 0; ! 893: ! 894: unmodify(); ! 895: initlist(curbuf); ! 896: setfname(curbuf, fname); ! 897: read_file(fname, 0); ! 898: SetLine(next_line(curbuf->b_first, lineno)); ! 899: } ! 900: ! 901: void ! 902: InsFile() ! 903: { ! 904: char *fname, ! 905: fnamebuf[FILESIZE]; ! 906: #ifdef MAC ! 907: if(Macmode) { ! 908: if(!(fname = gfile(fnamebuf))) return; ! 909: } ! 910: else ! 911: #endif /* MAC */ ! 912: fname = ask_file((char *) 0, curbuf->b_fname, fnamebuf); ! 913: read_file(fname, 1); ! 914: } ! 915: ! 916: #include "temp.h" ! 917: ! 918: int DOLsave = 0; /* Do Lsave flag. If lines aren't being save ! 919: when you think they should have been, this ! 920: flag is probably not being set, or is being ! 921: cleared before lsave() was called. */ ! 922: ! 923: private int nleft, /* number of good characters left in current block */ ! 924: tmpfd = -1; ! 925: disk_line DFree = 1; ! 926: /* pointer to end of tmp file */ ! 927: private char *tfname; ! 928: ! 929: void ! 930: tmpinit() ! 931: { ! 932: char buf[FILESIZE]; ! 933: ! 934: #ifdef MAC ! 935: sprintf(buf, "%s/%s", HomeDir, d_tempfile); ! 936: #else ! 937: sprintf(buf, "%s/%s", TmpFilePath, d_tempfile); ! 938: #endif ! 939: tfname = copystr(buf); ! 940: tfname = mktemp(tfname); ! 941: (void) close(creat(tfname, 0600)); ! 942: #ifndef MSDOS ! 943: tmpfd = open(tfname, 2); ! 944: #else /* MSDOS */ ! 945: tmpfd = open(tfname, 0x8002); /* MSDOS fix */ ! 946: #endif /* MSDOS */ ! 947: if (tmpfd == -1) ! 948: complain("Warning: cannot create tmp file!"); ! 949: } ! 950: ! 951: void ! 952: tmpclose() ! 953: { ! 954: if (tmpfd == -1) ! 955: return; ! 956: (void) close(tmpfd); ! 957: tmpfd = -1; ! 958: (void) unlink(tfname); ! 959: } ! 960: ! 961: /* get a line at `tl' in the tmp file into `buf' which should be LBSIZE ! 962: long */ ! 963: ! 964: int Jr_Len; /* length of Just Read Line */ ! 965: ! 966: #ifdef MAC /* The Lighspeed compiler can't copy with static here */ ! 967: char *getblock(); ! 968: #else ! 969: private char *getblock(); ! 970: #endif ! 971: void ! 972: getline(addr, buf) ! 973: disk_line addr; ! 974: register char *buf; ! 975: { ! 976: register char *bp, ! 977: *lp; ! 978: ! 979: lp = buf; ! 980: bp = getblock(addr >> 1, READ); ! 981: while (*lp++ = *bp++) ! 982: ; ! 983: Jr_Len = (lp - buf) - 1; ! 984: } ! 985: ! 986: /* Put `buf' and return the disk address */ ! 987: ! 988: disk_line ! 989: putline(buf) ! 990: char *buf; ! 991: { ! 992: register char *bp, ! 993: *lp; ! 994: register int nl; ! 995: disk_line free_ptr; ! 996: ! 997: lp = buf; ! 998: free_ptr = DFree; ! 999: bp = getblock(free_ptr, WRITE); ! 1000: nl = nleft; ! 1001: free_ptr = blk_round(free_ptr); ! 1002: while (*bp = *lp++) { ! 1003: if (*bp++ == '\n') { ! 1004: *--bp = 0; ! 1005: break; ! 1006: } ! 1007: if (--nl == 0) { ! 1008: free_ptr = forward_block(free_ptr); ! 1009: DFree = free_ptr; ! 1010: bp = getblock(free_ptr, WRITE); ! 1011: lp = buf; /* start over ... */ ! 1012: nl = nleft; ! 1013: } ! 1014: } ! 1015: free_ptr = DFree; ! 1016: DFree += (((lp - buf) + CH_SIZE - 1) / CH_SIZE); ! 1017: /* (lp - buf) includes the null */ ! 1018: return (free_ptr << 1); ! 1019: } ! 1020: ! 1021: /* The theory is that critical section of code inside this procedure ! 1022: will never cause a problem to occur. Basically, we need to ensure ! 1023: that two blocks are in memory at the same time, but I think that ! 1024: this can never screw up. */ ! 1025: ! 1026: #define lockblock(addr) ! 1027: #define unlockblock(addr) ! 1028: ! 1029: disk_line ! 1030: f_getputl(line, fp) ! 1031: Line *line; ! 1032: register File *fp; ! 1033: { ! 1034: register char *bp; ! 1035: register int c, ! 1036: nl, ! 1037: max = LBSIZE; ! 1038: disk_line free_ptr; ! 1039: char *base; ! 1040: #ifdef MSDOS ! 1041: char crleft = 0; ! 1042: #endif /* MSDOS */ ! 1043: ! 1044: free_ptr = DFree; ! 1045: base = bp = getblock(free_ptr, WRITE); ! 1046: nl = nleft; ! 1047: free_ptr = blk_round(free_ptr); ! 1048: while (--max > 0) { ! 1049: #ifdef MSDOS ! 1050: if (crleft) { ! 1051: c = crleft; ! 1052: crleft = 0; ! 1053: } else ! 1054: #endif /* MSDOS */ ! 1055: c = getc(fp); ! 1056: if (c == EOF || c == '\n') ! 1057: break; ! 1058: #ifdef MSDOS ! 1059: if (c == '\r') ! 1060: if ((crleft = getc(fp)) == '\n') { ! 1061: crleft = 0; ! 1062: break; ! 1063: } ! 1064: #endif /* MSDOS */ ! 1065: if (--nl == 0) { ! 1066: char *newbp; ! 1067: int nbytes; ! 1068: ! 1069: lockblock(free_ptr); ! 1070: DFree = free_ptr = forward_block(free_ptr); ! 1071: nbytes = bp - base; ! 1072: newbp = getblock(free_ptr, WRITE); ! 1073: nl = nleft; ! 1074: byte_copy(base, newbp, nbytes); ! 1075: bp = newbp + nbytes; ! 1076: base = newbp; ! 1077: unlockblock(free_ptr); ! 1078: } ! 1079: *bp++ = c; ! 1080: } ! 1081: *bp++ = '\0'; ! 1082: free_ptr = DFree; ! 1083: DFree += (((bp - base) + CH_SIZE - 1) / CH_SIZE); ! 1084: line->l_dline = (free_ptr << 1); ! 1085: if (max == 0) { ! 1086: add_mess(" [Line too long]"); ! 1087: rbell(); ! 1088: return EOF; ! 1089: } ! 1090: if (c == EOF) { ! 1091: if (--bp != base) ! 1092: add_mess(" [Incomplete last line]"); ! 1093: return EOF; ! 1094: } ! 1095: io_lines += 1; ! 1096: return 0; ! 1097: } ! 1098: ! 1099: typedef struct block { ! 1100: short b_dirty, ! 1101: b_bno; ! 1102: char b_buf[BUFSIZ]; ! 1103: struct block ! 1104: *b_LRUnext, ! 1105: *b_LRUprev, ! 1106: *b_HASHnext; ! 1107: } Block; ! 1108: ! 1109: #define HASHSIZE 7 /* Primes work best (so I'm told) */ ! 1110: #define B_HASH(bno) (bno % HASHSIZE) ! 1111: ! 1112: #ifdef MAC ! 1113: private Block *b_cache, ! 1114: #else ! 1115: private Block b_cache[NBUF], ! 1116: #endif ! 1117: *bht[HASHSIZE] = {0}, /* Block hash table */ ! 1118: *f_block = 0, ! 1119: *l_block = 0; ! 1120: private int max_bno = -1, ! 1121: NBlocks; ! 1122: ! 1123: #ifdef MAC ! 1124: void (*blkio)(); ! 1125: #else ! 1126: #ifdef LINT_ARGS ! 1127: private int (*blkio)(Block *, int (*)()); ! 1128: #else ! 1129: private int (*blkio)(); ! 1130: #endif ! 1131: #endif /* MAC */ ! 1132: ! 1133: #ifdef MAC ! 1134: make_cache() /* Only 32K of static space on Mac, so... */ ! 1135: { ! 1136: return((b_cache = (Block *) calloc(NBUF,sizeof(Block))) == 0 ? 0 : 1); ! 1137: } ! 1138: #endif /* MAC */ ! 1139: ! 1140: extern int read(), write(); ! 1141: ! 1142: private void ! 1143: real_blkio(b, iofcn) ! 1144: register Block *b; ! 1145: #ifdef MAC ! 1146: register int (*iofcn)(); ! 1147: #else ! 1148: #ifdef LINT_ARGS ! 1149: register int (*iofcn)(int, char *, unsigned int); ! 1150: #else ! 1151: register int (*iofcn)(); ! 1152: #endif ! 1153: #endif /* MAC */ ! 1154: { ! 1155: (void) lseek(tmpfd, (long) ((unsigned) b->b_bno) * BUFSIZ, 0); ! 1156: if ((*iofcn)(tmpfd, b->b_buf, BUFSIZ) != BUFSIZ) ! 1157: error("[Tmp file %s error; to continue editing would be dangerous]", (iofcn == read) ? "READ" : "WRITE"); ! 1158: } ! 1159: ! 1160: private void ! 1161: fake_blkio(b, iofcn) ! 1162: register Block *b; ! 1163: register int (*iofcn)(); ! 1164: { ! 1165: tmpinit(); ! 1166: blkio = real_blkio; ! 1167: real_blkio(b, iofcn); ! 1168: } ! 1169: ! 1170: void ! 1171: d_cache_init() ! 1172: { ! 1173: register Block *bp, /* Block pointer */ ! 1174: **hp; /* Hash pointer */ ! 1175: register short bno; ! 1176: ! 1177: for (bp = b_cache, bno = NBUF; --bno >= 0; bp++) { ! 1178: NBlocks += 1; ! 1179: bp->b_dirty = 0; ! 1180: bp->b_bno = bno; ! 1181: if (l_block == 0) ! 1182: l_block = bp; ! 1183: bp->b_LRUprev = 0; ! 1184: bp->b_LRUnext = f_block; ! 1185: if (f_block != 0) ! 1186: f_block->b_LRUprev = bp; ! 1187: f_block = bp; ! 1188: ! 1189: bp->b_HASHnext = *(hp = &bht[B_HASH(bno)]); ! 1190: *hp = bp; ! 1191: } ! 1192: blkio = fake_blkio; ! 1193: } ! 1194: ! 1195: void ! 1196: SyncTmp() ! 1197: { ! 1198: register Block *b; ! 1199: #ifdef IBMPC ! 1200: register int bno = 0; ! 1201: Block *lookup(); ! 1202: ! 1203: /* sync the blocks in order, for floppy disks */ ! 1204: for (bno = 0; bno <= max_bno; ) { ! 1205: if ((b = lookup(bno++)) && b->b_dirty) { ! 1206: (*blkio)(b, write); ! 1207: b->b_dirty = 0; ! 1208: } ! 1209: } ! 1210: #else ! 1211: for (b = f_block; b != 0; b = b->b_LRUnext) ! 1212: if (b->b_dirty) { ! 1213: (*blkio)(b, write); ! 1214: b->b_dirty = 0; ! 1215: } ! 1216: #endif ! 1217: } ! 1218: ! 1219: private Block * ! 1220: lookup(bno) ! 1221: register short bno; ! 1222: { ! 1223: register Block *bp; ! 1224: ! 1225: for (bp = bht[B_HASH(bno)]; bp != 0; bp = bp->b_HASHnext) ! 1226: if (bp->b_bno == bno) ! 1227: break; ! 1228: return bp; ! 1229: } ! 1230: ! 1231: private void ! 1232: LRUunlink(b) ! 1233: register Block *b; ! 1234: { ! 1235: if (b->b_LRUprev == 0) ! 1236: f_block = b->b_LRUnext; ! 1237: else ! 1238: b->b_LRUprev->b_LRUnext = b->b_LRUnext; ! 1239: if (b->b_LRUnext == 0) ! 1240: l_block = b->b_LRUprev; ! 1241: else ! 1242: b->b_LRUnext->b_LRUprev = b->b_LRUprev; ! 1243: } ! 1244: ! 1245: private Block * ! 1246: b_unlink(bp) ! 1247: register Block *bp; ! 1248: { ! 1249: register Block *hp, ! 1250: *prev = 0; ! 1251: ! 1252: LRUunlink(bp); ! 1253: /* Now that we have the block, we remove it from its position ! 1254: in the hash table, so we can THEN put it somewhere else with ! 1255: it's new block assignment. */ ! 1256: ! 1257: for (hp = bht[B_HASH(bp->b_bno)]; hp != 0; prev = hp, hp = hp->b_HASHnext) ! 1258: if (hp == bp) ! 1259: break; ! 1260: if (hp == 0) { ! 1261: printf("\rBlock %d missing!", bp->b_bno); ! 1262: finish(0); ! 1263: } ! 1264: if (prev) ! 1265: prev->b_HASHnext = hp->b_HASHnext; ! 1266: else ! 1267: bht[B_HASH(bp->b_bno)] = hp->b_HASHnext; ! 1268: ! 1269: if (bp->b_dirty) { /* do, now, the delayed write */ ! 1270: (*blkio)(bp, write); ! 1271: bp->b_dirty = 0; ! 1272: } ! 1273: ! 1274: return bp; ! 1275: } ! 1276: ! 1277: /* Get a block which contains at least part of the line with the address ! 1278: atl. Returns a pointer to the block and sets the global variable ! 1279: nleft (number of good characters left in the buffer). */ ! 1280: ! 1281: private char * ! 1282: getblock(atl, iof) ! 1283: disk_line atl; ! 1284: { ! 1285: register int bno, ! 1286: off; ! 1287: register Block *bp; ! 1288: static Block *lastb = 0; ! 1289: ! 1290: bno = da_to_bno(atl); ! 1291: off = da_to_off(atl); ! 1292: if (da_too_huge(atl)) ! 1293: error("Tmp file too large. Get help!"); ! 1294: nleft = BUFSIZ - off; ! 1295: if (lastb != 0 && lastb->b_bno == bno) { ! 1296: lastb->b_dirty |= iof; ! 1297: return lastb->b_buf + off; ! 1298: } ! 1299: ! 1300: /* The requested block already lives in memory, so we move ! 1301: it to the end of the LRU list (making it Most Recently Used) ! 1302: and then return a pointer to it. */ ! 1303: if (bp = lookup(bno)) { ! 1304: if (bp != l_block) { ! 1305: LRUunlink(bp); ! 1306: if (l_block == 0) ! 1307: f_block = l_block = bp; ! 1308: else ! 1309: l_block->b_LRUnext = bp; ! 1310: bp->b_LRUprev = l_block; ! 1311: l_block = bp; ! 1312: bp->b_LRUnext = 0; ! 1313: } ! 1314: if (bp->b_bno > max_bno) ! 1315: max_bno = bp->b_bno; ! 1316: bp->b_dirty |= iof; ! 1317: lastb = bp; ! 1318: return bp->b_buf + off; ! 1319: } ! 1320: ! 1321: /* The block we want doesn't reside in memory so we take the ! 1322: least recently used clean block (if there is one) and use ! 1323: it. */ ! 1324: bp = f_block; ! 1325: if (bp->b_dirty) /* The best block is dirty ... */ ! 1326: SyncTmp(); ! 1327: ! 1328: bp = b_unlink(bp); ! 1329: if (l_block == 0) ! 1330: l_block = f_block = bp; ! 1331: else ! 1332: l_block->b_LRUnext = bp; /* Place it at the end ... */ ! 1333: bp->b_LRUprev = l_block; ! 1334: l_block = bp; ! 1335: bp->b_LRUnext = 0; /* so it's Most Recently Used */ ! 1336: ! 1337: bp->b_dirty = iof; ! 1338: bp->b_bno = bno; ! 1339: bp->b_HASHnext = bht[B_HASH(bno)]; ! 1340: bht[B_HASH(bno)] = bp; ! 1341: ! 1342: /* Get the current contents of the block UNLESS this is a new ! 1343: block that's never been looked at before, i.e., it's past ! 1344: the end of the tmp file. */ ! 1345: ! 1346: if (bp->b_bno <= max_bno) ! 1347: (*blkio)(bp, read); ! 1348: else ! 1349: max_bno = bno; ! 1350: ! 1351: lastb = bp; ! 1352: return bp->b_buf + off; ! 1353: } ! 1354: ! 1355: char * ! 1356: lbptr(line) ! 1357: Line *line; ! 1358: { ! 1359: return getblock(line->l_dline >> 1, READ); ! 1360: } ! 1361: ! 1362: /* save the current contents of linebuf, if it has changed */ ! 1363: ! 1364: void ! 1365: lsave() ! 1366: { ! 1367: if (curbuf == 0 || !DOLsave) /* Nothing modified recently */ ! 1368: return; ! 1369: ! 1370: if (strcmp(lbptr(curline), linebuf) != 0) ! 1371: SavLine(curline, linebuf); /* Put linebuf on the disk. */ ! 1372: DOLsave = 0; ! 1373: } ! 1374: ! 1375: #ifdef BACKUPFILES ! 1376: void ! 1377: file_backup(fname) ! 1378: char *fname; ! 1379: { ! 1380: #ifndef MSDOS ! 1381: char *s; ! 1382: register int i; ! 1383: int fd1, ! 1384: fd2; ! 1385: char tmp1[BUFSIZ], ! 1386: tmp2[BUFSIZ]; ! 1387: struct stat buf; ! 1388: int mode; ! 1389: ! 1390: strcpy(tmp1, fname); ! 1391: if ((s = rindex(tmp1, '/')) == NULL) ! 1392: sprintf(tmp2, "#%s", fname); ! 1393: else { ! 1394: *s++ = '\0'; ! 1395: sprintf(tmp2, "%s/#%s", tmp1, s); ! 1396: } ! 1397: ! 1398: if ((fd1 = open(fname, 0)) < 0) ! 1399: return; ! 1400: ! 1401: /* create backup file with same mode as input file */ ! 1402: #ifndef MAC ! 1403: if (fstat(fd1, &buf) != 0) ! 1404: mode = CreatMode; ! 1405: else ! 1406: #endif ! 1407: mode = buf.st_mode; ! 1408: ! 1409: if ((fd2 = creat(tmp2, mode)) < 0) { ! 1410: (void) close(fd1); ! 1411: return; ! 1412: } ! 1413: while ((i = read(fd1, tmp1, sizeof(tmp1))) > 0) ! 1414: write(fd2, tmp1, i); ! 1415: #ifdef BSD4_2 ! 1416: (void) fsync(fd2); ! 1417: #endif ! 1418: (void) close(fd2); ! 1419: (void) close(fd1); ! 1420: #else /* MSDOS */ ! 1421: char *dot, ! 1422: *slash, ! 1423: tmp[FILESIZE]; ! 1424: ! 1425: strcpy(tmp, fname); ! 1426: slash = basename(tmp); ! 1427: if (dot = rindex(slash, '.')) { ! 1428: if (!stricmp(dot,".bak")) ! 1429: return; ! 1430: else *dot = 0; ! 1431: } ! 1432: strcat(tmp, ".bak"); ! 1433: unlink(tmp); ! 1434: rename(fname, tmp); ! 1435: #endif /* MSDOS */ ! 1436: } ! 1437: #endif ! 1438: ! 1439: #if defined(MSDOS) && defined (CHDIR) ! 1440: ! 1441: private int /* chdir + drive */ ! 1442: Dchdir(to) ! 1443: char *to; ! 1444: { ! 1445: unsigned d, dd, n; ! 1446: ! 1447: if (to[1] == ':') { ! 1448: d = to[0]; ! 1449: if (d >= 'a') d = d - 'a' + 1; ! 1450: if (d >= 'A') d = d - 'A' + 1; ! 1451: _dos_getdrive(&dd); ! 1452: if (dd != d) ! 1453: _dos_setdrive(d, &n); ! 1454: if (to[2] == 0) ! 1455: return 0; ! 1456: } ! 1457: return chdir(to); ! 1458: } ! 1459: ! 1460: private char * ! 1461: fixpath(p) ! 1462: char *p; ! 1463: { ! 1464: char *pp = p; ! 1465: ! 1466: while (*p) { ! 1467: if (*p == '\\') ! 1468: *p = '/'; ! 1469: p++; ! 1470: } ! 1471: return(strlwr(pp)); ! 1472: } ! 1473: ! 1474: ! 1475: private void ! 1476: abspath(so, dest) ! 1477: char *so, *dest; ! 1478: { ! 1479: char cwd[FILESIZE], cwdD[3], cwdDIR[FILESIZE], cwdF[9], cwdEXT[5], ! 1480: soD[3], soDIR[FILESIZE], soF[9], soEXT[5]; ! 1481: char *drive, *path; ! 1482: ! 1483: _splitpath(fixpath(so), soD, soDIR, soF, soEXT); ! 1484: getcwd(cwd, FILESIZE); ! 1485: if (*soD != 0) { ! 1486: Dchdir(soD); /* this is kinda messy */ ! 1487: getcwd(cwdDIR, FILESIZE); /* should probably just */ ! 1488: Dchdir(cwd); /* call DOS to do it */ ! 1489: strcpy(cwd, cwdDIR); ! 1490: } ! 1491: (void) fixpath(cwd); ! 1492: if (cwd[strlen(cwd)-1] != '/') ! 1493: strcat(cwd, "/x.x"); /* need dummy filename */ ! 1494: ! 1495: _splitpath(fixpath(cwd), cwdD, cwdDIR, cwdF, cwdEXT); ! 1496: ! 1497: drive = (*soD == 0) ? cwdD : soD; ! 1498: ! 1499: if (*soDIR != '/') ! 1500: path = strcat(cwdDIR, soDIR); ! 1501: else ! 1502: path = soDIR; ! 1503: _makepath(dest, drive, path, soF, soEXT); ! 1504: fixpath(dest); /* can't do it often enough */ ! 1505: } ! 1506: ! 1507: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.