Annotation of 43BSDTahoe/new/jove/io.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.