Annotation of 43BSD/contrib/jove/io.c, revision 1.1

1.1     ! root        1: /*************************************************************************
        !             2:  * This program is copyright (C) 1985, 1986 by Jonathan Payne.  It is    *
        !             3:  * provided to you without charge for use only on a licensed Unix        *
        !             4:  * system.  You may copy JOVE provided that this notice is included with *
        !             5:  * the copy.  You may not sell copies of this program or versions        *
        !             6:  * modified for use on microcomputer systems, unless the copies are      *
        !             7:  * included with a Unix system distribution and the source is provided.  *
        !             8:  *************************************************************************/
        !             9: 
        !            10: #include "jove.h"
        !            11: #include "io.h"
        !            12: #include "termcap.h"
        !            13: 
        !            14: #ifdef IPROCS
        !            15: #      include <signal.h>
        !            16: #endif
        !            17: 
        !            18: #include <sys/stat.h>
        !            19: #include <sys/file.h>
        !            20: #include <errno.h>
        !            21: 
        !            22: long   io_chars;               /* number of chars in this open_file */
        !            23: int    io_lines;               /* number of lines in this open_file */
        !            24: private int    tellall;        /* display file io info? */
        !            25: 
        !            26: #ifdef VMUNIX
        !            27: char   iobuff[LBSIZE],
        !            28:        genbuf[LBSIZE],
        !            29:        linebuf[LBSIZE];
        !            30: #else
        !            31: char   *iobuff,
        !            32:        *genbuf,
        !            33:        *linebuf;
        !            34: #endif
        !            35: 
        !            36: #ifdef BACKUPFILES
        !            37: int    BkupOnWrite = 0;
        !            38: #endif
        !            39: 
        !            40: close_file(fp)
        !            41: File   *fp;
        !            42: {
        !            43:        if (fp) {
        !            44:                f_close(fp);
        !            45:                if (tellall != QUIET)
        !            46:                        add_mess(" %d lines, %D characters.",
        !            47:                                 io_lines,
        !            48:                                 io_chars);
        !            49:        }
        !            50: }
        !            51: 
        !            52: /* Write the region from line1/char1 to line2/char2 to FP.  This
        !            53:    never CLOSES the file since we don't know if we want to. */
        !            54: 
        !            55: int    EndWNewline = 1;
        !            56: 
        !            57: putreg(fp, line1, char1, line2, char2, makesure)
        !            58: register File  *fp;
        !            59: Line   *line1,
        !            60:        *line2;
        !            61: {
        !            62:        register int    c;
        !            63:        register char   *lp;
        !            64: 
        !            65:        if (makesure)
        !            66:                (void) fixorder(&line1, &char1, &line2, &char2);
        !            67:        while (line1 != line2->l_next) {
        !            68:                lp = lcontents(line1) + char1;
        !            69:                if (line1 == line2)
        !            70:                        fputnchar(lp, (char2 - char1), fp);
        !            71:                else while (c = *lp++) {
        !            72:                        putc(c, fp);
        !            73:                        io_chars++;
        !            74:                }
        !            75:                if (line1 != line2) {
        !            76:                        io_lines++;
        !            77:                        io_chars++;
        !            78:                        putc('\n', fp);
        !            79:                }
        !            80:                line1 = line1->l_next;
        !            81:                char1 = 0;
        !            82:        }
        !            83:        flush(fp);
        !            84: }
        !            85: 
        !            86: read_file(file, is_insert)
        !            87: char   *file;
        !            88: {
        !            89:        Bufpos  save;
        !            90:        File    *fp;
        !            91: 
        !            92:        if (!is_insert) {
        !            93:                curbuf->b_ntbf = 0;
        !            94:                set_ino(curbuf);
        !            95:        }
        !            96:        fp = open_file(file, iobuff, F_READ, !COMPLAIN, !QUIET);
        !            97:        if (fp == NIL) {
        !            98:                if (!is_insert && errno == ENOENT)
        !            99:                        s_mess("(new file)");
        !           100:                else
        !           101:                        s_mess(IOerr("open", file));
        !           102:                return;
        !           103:        }
        !           104:        DOTsave(&save);
        !           105:        dofread(fp);
        !           106:        SetDot(&save);
        !           107:        if (is_insert && io_chars > 0)
        !           108:                modify();
        !           109:        getDOT();
        !           110:        close_file(fp);
        !           111: }
        !           112: 
        !           113: dofread(fp)
        !           114: register File  *fp;
        !           115: {
        !           116:        char    end[LBSIZE];
        !           117:        int     xeof = 0;
        !           118:        Line    *savel = curline;
        !           119:        int     savec = curchar;
        !           120: 
        !           121:        strcpy(end, linebuf + curchar);
        !           122:        xeof = f_gets(fp, linebuf + curchar, LBSIZE - curchar);
        !           123:        SavLine(curline, linebuf);
        !           124:        if (!xeof) do {
        !           125:                xeof = f_gets(fp, linebuf, LBSIZE);
        !           126:                curline = listput(curbuf, curline);
        !           127:                curline->l_dline = putline(linebuf) | DIRTY;
        !           128:        } while (!xeof);
        !           129:        linecopy(linebuf, (curchar = strlen(linebuf)), end);
        !           130:        SavLine(curline, linebuf);
        !           131:        IFixMarks(savel, savec, curline, curchar);
        !           132: }
        !           133: 
        !           134: SaveFile()
        !           135: {
        !           136:        if (IsModified(curbuf)) {
        !           137:                if (curbuf->b_fname == 0)
        !           138:                        WriteFile();
        !           139:                else {
        !           140:                        filemunge(curbuf->b_fname);
        !           141:                        chk_mtime(curbuf->b_fname, "save");
        !           142:                        file_write(curbuf->b_fname, 0);
        !           143:                        unmodify();
        !           144:                }
        !           145:        } else
        !           146:                message("No changes need to be written.");
        !           147: }
        !           148: 
        !           149: char   *HomeDir;       /* home directory */
        !           150: int    HomeLen = -1;   /* length of home directory string */
        !           151: 
        !           152: #ifndef CHDIR
        !           153: 
        !           154: char *
        !           155: pr_name(fname)
        !           156: char   *fname;
        !           157: {
        !           158:        if (fname == 0)
        !           159:                return 0;
        !           160: 
        !           161:        if (strncmp(fname, HomeDir, HomeLen) == 0) {
        !           162:                static char     name_buf[100];
        !           163: 
        !           164:                sprintf(name_buf, "~%s", fname + HomeLen);
        !           165:                return name_buf;
        !           166:        }
        !           167: 
        !           168:        return fname;
        !           169: }
        !           170: 
        !           171: #else
        !           172: 
        !           173: #define NDIRS  5
        !           174: 
        !           175: private char   *DirStack[NDIRS] = {0};
        !           176: private int    DirSP = 0;      /* Directory stack pointer */
        !           177: #define PWD    (DirStack[DirSP])
        !           178: 
        !           179: char *
        !           180: pwd()
        !           181: {
        !           182:        return PWD;
        !           183: }
        !           184: 
        !           185: char *
        !           186: pr_name(fname)
        !           187: char   *fname;
        !           188: {
        !           189:        int     n;
        !           190: 
        !           191:        if (fname == 0)
        !           192:                return 0;
        !           193:        n = numcomp(fname, PWD);
        !           194: 
        !           195:        if ((PWD[n] == 0) &&    /* Matched to end of PWD */
        !           196:            (fname[n] == '/'))
        !           197:                return fname + n + 1;
        !           198: 
        !           199:        if (strcmp(HomeDir, "/") != 0 && strncmp(fname, HomeDir, HomeLen) == 0) {
        !           200:                static char     name_buf[100];
        !           201: 
        !           202:                sprintf(name_buf, "~%s", fname + HomeLen);
        !           203:                return name_buf;
        !           204:        }
        !           205: 
        !           206:        return fname;   /* return entire path name */
        !           207: }
        !           208: 
        !           209: Chdir()
        !           210: {
        !           211:        char    dirbuf[FILESIZE];
        !           212: 
        !           213:        (void) ask_file(PWD, dirbuf);
        !           214:        if (chdir(dirbuf) == -1) {
        !           215:                s_mess("cd: cannot change into %s.", dirbuf);
        !           216:                return;
        !           217:        }
        !           218:        UpdModLine++;
        !           219:        setCWD(dirbuf);
        !           220: }
        !           221: 
        !           222: #ifndef JOB_CONTROL
        !           223: char *
        !           224: getwd()
        !           225: {
        !           226:        Buffer  *old = curbuf;
        !           227:        char    *ret_val;
        !           228: 
        !           229:        SetBuf(do_select((Window *) 0, "pwd-output"));
        !           230:        curbuf->b_type = B_PROCESS;
        !           231:        (void) UnixToBuf("pwd-output", NO, 0, YES, "/bin/pwd", "pwd", 0);
        !           232:        ToFirst();
        !           233:        ret_val = sprint(linebuf);
        !           234:        SetBuf(old);
        !           235:        return ret_val;
        !           236: }
        !           237: #endif
        !           238: 
        !           239: setCWD(d)
        !           240: char   *d;
        !           241: {
        !           242:        if (PWD == 0)
        !           243:                PWD = malloc((unsigned) strlen(d) + 1);
        !           244:        else {
        !           245:                extern char     *ralloc();
        !           246: 
        !           247:                PWD = ralloc(PWD, strlen(d) + 1);
        !           248:        }
        !           249:        strcpy(PWD, d);
        !           250: }
        !           251: 
        !           252: getCWD()
        !           253: {
        !           254:        char    *cwd = getenv("CWD");
        !           255: #ifdef JOB_CONTROL
        !           256:        extern char     *getwd();
        !           257:        char    pathname[FILESIZE];
        !           258: #endif
        !           259: 
        !           260:        if (cwd == 0)
        !           261: #ifdef JOB_CONTROL
        !           262:                cwd = getwd(pathname);
        !           263: #else
        !           264:                cwd = getwd();
        !           265: #endif
        !           266: 
        !           267:        setCWD(cwd);
        !           268: }      
        !           269: 
        !           270: prDIRS()
        !           271: {
        !           272:        register int    i;
        !           273: 
        !           274:        s_mess(": %f ");
        !           275:        for (i = DirSP; i >= 0; i--)
        !           276:                add_mess("%s ", pr_name(DirStack[i]));
        !           277: }
        !           278: 
        !           279: prCWD()
        !           280: {
        !           281:        s_mess(": %f => \"%s\"", PWD);
        !           282: }
        !           283: 
        !           284: Pushd()
        !           285: {
        !           286:        char    *newdir,
        !           287:                dirbuf[FILESIZE];
        !           288: 
        !           289:        newdir = ask_file(NullStr, dirbuf);     /* Parses directories ... */
        !           290:        UpdModLine++;
        !           291:        if (*newdir == 0) {     /* Wants to swap top two entries */
        !           292:                char    *old_top;
        !           293: 
        !           294:                if (DirSP == 0)
        !           295:                        complain("pushd: no other directory.");
        !           296:                old_top = PWD;
        !           297:                DirStack[DirSP] = DirStack[DirSP - 1];
        !           298:                DirStack[DirSP - 1] = old_top;
        !           299:                (void) chdir(PWD);
        !           300:        } else {
        !           301:                if (chdir(dirbuf) == -1) {
        !           302:                        s_mess("pushd: cannot change into %s.", dirbuf);
        !           303:                        return;
        !           304:                }
        !           305: 
        !           306:                if (DirSP + 1 >= NDIRS)
        !           307:                        complain("pushd: full stack; max of %d pushes.", NDIRS);
        !           308:                DirSP++;
        !           309:                setCWD(dirbuf);
        !           310:        }
        !           311:        prDIRS();
        !           312: }
        !           313: 
        !           314: Popd()
        !           315: {
        !           316:        if (DirSP == 0)
        !           317:                complain("popd: directory stack is empty.");
        !           318:        UpdModLine++;
        !           319:        free(PWD);
        !           320:        PWD = 0;
        !           321:        DirSP--;
        !           322:        (void) chdir(PWD);      /* If this doesn't work, we's in deep shit. */
        !           323:        prDIRS();
        !           324: }
        !           325: 
        !           326: private char *
        !           327: dbackup(base, offset, c)
        !           328: register char  *base,
        !           329:                *offset,
        !           330:                c;
        !           331: {
        !           332:        while (offset > base && *--offset != c)
        !           333:                ;
        !           334:        return offset;
        !           335: }
        !           336: 
        !           337: dfollow(file, into)
        !           338: char   *file,
        !           339:        *into;
        !           340: {
        !           341:        char    *dp,
        !           342:                *sp;
        !           343: 
        !           344:        if (*file == '/') {             /* Absolute pathname */
        !           345:                strcpy(into, "/");
        !           346:                file++;
        !           347:        } else
        !           348:                strcpy(into, PWD);
        !           349:        dp = into + strlen(into);
        !           350: 
        !           351:        sp = file;
        !           352:        do {
        !           353:                if (*file == 0)
        !           354:                        break;
        !           355:                if (sp = index(file, '/'))
        !           356:                        *sp = 0;
        !           357:                if (strcmp(file, ".") == 0)
        !           358:                        ;       /* So it will get to the end of the loop */
        !           359:                else if (strcmp(file, "..") == 0) {
        !           360:                        *(dp = dbackup(into, dp, '/')) = 0;
        !           361:                        if (dp == into)
        !           362:                                strcpy(into, "/"), dp = into + 1;
        !           363:                } else {
        !           364:                        if (into[strlen(into) - 1] != '/')
        !           365:                                (void) strcat(into, "/");
        !           366:                        (void) strcat(into, file);
        !           367:                        dp += strlen(file);     /* stay at the end */
        !           368:                }
        !           369:                file = sp + 1;
        !           370:        } while (sp != 0);
        !           371: }
        !           372: 
        !           373: #endif CHDIR
        !           374: 
        !           375: get_hdir(user, buf)
        !           376: register char  *user,
        !           377:                *buf;
        !           378: {
        !           379:        char    fbuf[LBSIZE],
        !           380:                pattern[100];
        !           381:        register int    u_len;
        !           382:        File    *fp;
        !           383: 
        !           384:        u_len = strlen(user);
        !           385:        fp = open_file("/etc/passwd", fbuf, F_READ, COMPLAIN, QUIET);
        !           386:        sprintf(pattern, "%s:[^:]*:[^:]*:[^:]*:[^:]*:\\([^:]*\\):", user);
        !           387:        while (f_gets(fp, genbuf, LBSIZE) != EOF)
        !           388:                if ((strncmp(genbuf, user, u_len) == 0) &&
        !           389:                    (LookingAt(pattern, genbuf, 0))) {
        !           390:                        putmatch(1, buf, FILESIZE);
        !           391:                        close_file(fp);
        !           392:                        return;
        !           393:                }
        !           394:        f_close(fp);
        !           395:        complain("[unknown user: %s]", user);
        !           396: }
        !           397: 
        !           398: PathParse(name, intobuf)
        !           399: char   *name,
        !           400:        *intobuf;
        !           401: {
        !           402:        char    localbuf[FILESIZE];
        !           403: 
        !           404:        intobuf[0] = localbuf[0] = '\0';
        !           405:        if (*name == '\0')
        !           406:                return;
        !           407:        if (*name == '~') {
        !           408:                if (name[1] == '/' || name[1] == '\0') {
        !           409:                        strcpy(localbuf, HomeDir);
        !           410:                        name++;
        !           411:                } else {
        !           412:                        char    *uendp = index(name, '/'),
        !           413:                                unamebuf[30];
        !           414: 
        !           415:                        if (uendp == 0)
        !           416:                                uendp = name + strlen(name);
        !           417:                        name = name + 1;
        !           418:                        null_ncpy(unamebuf, name, uendp - name);
        !           419:                        get_hdir(unamebuf, localbuf);
        !           420:                        name = uendp;
        !           421:                }
        !           422:        } else if (*name == '\\')
        !           423:                name++;
        !           424:        (void) strcat(localbuf, name);
        !           425: #ifdef CHDIR
        !           426:        dfollow(localbuf, intobuf);
        !           427: #else
        !           428:        strcpy(intobuf, localbuf);
        !           429: #endif
        !           430: }
        !           431: 
        !           432: filemunge(newname)
        !           433: char   *newname;
        !           434: {
        !           435:        struct stat     stbuf;
        !           436: 
        !           437:        if (newname == 0)
        !           438:                return;
        !           439:        if (stat(newname, &stbuf))
        !           440:                return;
        !           441:        if ((stbuf.st_ino != curbuf->b_ino) &&
        !           442:            ((stbuf.st_mode & S_IFMT) != S_IFCHR) &&
        !           443:            (strcmp(newname, curbuf->b_fname) != 0)) {
        !           444:                rbell();
        !           445:                confirm("\"%s\" already exists; overwrite it? ", newname);
        !           446:        }
        !           447: }
        !           448: 
        !           449: WrtReg()
        !           450: {
        !           451:        DoWriteReg(0);
        !           452: }
        !           453: 
        !           454: AppReg()
        !           455: {
        !           456:        DoWriteReg(1);
        !           457: }
        !           458: 
        !           459: int    CreatMode = DFLT_MODE;
        !           460: 
        !           461: DoWriteReg(app)
        !           462: {
        !           463:        char    fnamebuf[FILESIZE],
        !           464:                *fname;
        !           465:        Mark    *mp = CurMark();
        !           466:        File    *fp;
        !           467: 
        !           468:        /* Won't get here if there isn't a Mark */
        !           469:        fname = ask_file((char *) 0, fnamebuf);
        !           470: 
        !           471: #ifdef BACKUPFILES
        !           472:        if (!app) {
        !           473:                filemunge(fname);
        !           474: 
        !           475:                if (BkupOnWrite)
        !           476:                        file_backup(fname);
        !           477:        }
        !           478: #else
        !           479:        if (!app)
        !           480:                filemunge(fname);
        !           481: #endif
        !           482: 
        !           483:        fp = open_file(fname, iobuff, app ? F_APPEND : F_WRITE, COMPLAIN, !QUIET);
        !           484:        putreg(fp, mp->m_line, mp->m_char, curline, curchar, YES);
        !           485:        close_file(fp);
        !           486: }
        !           487: 
        !           488: int    OkayBadChars = 0;
        !           489: 
        !           490: WriteFile()
        !           491: {
        !           492:        char    *fname,
        !           493:                fnamebuf[FILESIZE];
        !           494: 
        !           495:        fname = ask_file(curbuf->b_fname, fnamebuf);
        !           496:        /* Don't allow bad characters when creating new files. */
        !           497:        if (!OkayBadChars && strcmp(curbuf->b_fname, fnamebuf) != 0) {
        !           498:                static char     *badchars = "!$^&*()~`{}\"'\\|<>? ";
        !           499:                register char   *cp = fnamebuf;
        !           500:                register int    c;
        !           501: 
        !           502:                while (c = *cp++)
        !           503:                        if (c < ' ' || c == '\177' || index(badchars, c))
        !           504:                                complain("'%p': bad character in filename.", c);
        !           505:        }
        !           506: 
        !           507:        chk_mtime(fname, "write");
        !           508:        filemunge(fname);
        !           509:        if (curbuf->b_type != B_IPROCESS)
        !           510:                curbuf->b_type = B_FILE;  /* In case it wasn't before. */
        !           511:        setfname(curbuf, fname);
        !           512:        file_write(fname, 0);
        !           513:        unmodify();
        !           514: }
        !           515: 
        !           516: File *
        !           517: open_file(fname, buf, how, ifbad, loudness)
        !           518: register char  *fname;
        !           519: char   *buf;
        !           520: register int   how;
        !           521: {
        !           522:        register File   *fp;
        !           523: 
        !           524:        io_chars = 0;
        !           525:        io_lines = 0;
        !           526:        tellall = loudness;
        !           527: 
        !           528:        fp = f_open(fname, how, buf, LBSIZE);
        !           529:        if (fp == NIL) {
        !           530:                 message(IOerr((how == F_READ) ? "open" : "create", fname));
        !           531:                if (ifbad == COMPLAIN)
        !           532:                        complain((char *) 0);
        !           533:        } else {
        !           534:                int     readonly = FALSE;
        !           535: 
        !           536:                if (access(fname, W_OK) == -1 && errno != ENOENT)
        !           537:                        readonly = TRUE;
        !           538:                                                         
        !           539:                if (loudness != QUIET)
        !           540:                        f_mess("\"%s\"%s", pr_name(fname),
        !           541:                                   readonly ? " [Read only]" : NullStr);
        !           542:        }
        !           543:        return fp;
        !           544: }
        !           545: 
        !           546: /* Check to see if the file has been modified since it was
        !           547:    last written.  If so, make sure they know what they're
        !           548:    doing.
        !           549: 
        !           550:    I hate to use another stat(), but to use confirm we gotta
        !           551:    do this before we open the file. */
        !           552: 
        !           553: chk_mtime(fname, how)
        !           554: char   *fname,
        !           555:        *how;
        !           556: {
        !           557:        struct stat     stbuf;
        !           558:        Buffer  *b;
        !           559:        char    *mesg = "Shall I go ahead and %s anyway? ";
        !           560: 
        !           561:        if ((curbuf->b_mtime != 0) &&           /* if we care ... */
        !           562:            (b = file_exists(fname)) &&         /* we already have this file */
        !           563:            (b == curbuf) &&                    /* and it's the current buffer */
        !           564:            (stat(fname, &stbuf) != -1) &&      /* and we can stat it */
        !           565:            (stbuf.st_mtime != b->b_mtime)) {   /* and there's trouble. */
        !           566:                rbell();
        !           567:                redisplay();    /* Ring that bell! */
        !           568:                TOstart("Warning", TRUE);
        !           569:                Typeout("\"%s\" now saved on disk is not what you last", pr_name(fname));
        !           570:                Typeout("visited or saved.  Probably someone else is editing");
        !           571:                Typeout("your file at the same time.  Type \"y\" if I should");
        !           572:                Typeout("%s anyway.", how);
        !           573:                f_mess(mesg, how);
        !           574:                TOstop();
        !           575:                confirm(mesg, how);
        !           576:        }
        !           577: }
        !           578: 
        !           579: file_write(fname, app)
        !           580: char   *fname;
        !           581: {
        !           582:        File    *fp;
        !           583: 
        !           584: #ifdef BACKUPFILES
        !           585:        if (!app && BkupOnWrite)
        !           586:                file_backup(fname);
        !           587: #endif
        !           588: 
        !           589:        fp = open_file(fname, iobuff, app ? F_APPEND : F_WRITE, COMPLAIN, !QUIET);
        !           590: 
        !           591:        if (EndWNewline) {      /* Make sure file ends with a newLine */
        !           592:                Bufpos  save;
        !           593: 
        !           594:                DOTsave(&save);
        !           595:                ToLast();
        !           596:                if (length(curline))    /* Not a blank Line */
        !           597:                        DoTimes(LineInsert(), 1);       /* Make it blank */
        !           598:                SetDot(&save);
        !           599:        }
        !           600:        putreg(fp, curbuf->b_first, 0, curbuf->b_last, length(curbuf->b_last), NO);
        !           601:        set_ino(curbuf);
        !           602:        close_file(fp);
        !           603: }
        !           604: 
        !           605: ReadFile()
        !           606: {
        !           607:        char    *fname,
        !           608:                fnamebuf[FILESIZE];
        !           609: 
        !           610:        fname = ask_file(curbuf->b_fname, fnamebuf);
        !           611:        chk_mtime(fname, "read");
        !           612: 
        !           613:        if (IsModified(curbuf)) {
        !           614:                char    *y_or_n;
        !           615:                int     c;
        !           616: 
        !           617:                for (;;) {
        !           618:                        rbell();
        !           619:                        y_or_n = ask(NullStr, "Shall I make your changes to \"%s\" permanent? ", curbuf->b_name);
        !           620:                        c = Upper(*y_or_n);
        !           621:                        if (c == 'Y' || c == 'N')
        !           622:                                break;
        !           623:                }                       
        !           624:                if (c == 'Y')
        !           625:                        SaveFile();
        !           626:        }
        !           627: 
        !           628:        unmodify();
        !           629:        initlist(curbuf);
        !           630:        setfname(curbuf, fname);
        !           631:        read_file(fname, 0);
        !           632: }
        !           633: 
        !           634: InsFile()
        !           635: {
        !           636:        char    *fname,
        !           637:                fnamebuf[FILESIZE];
        !           638: 
        !           639:        fname = ask_file(curbuf->b_fname, fnamebuf);
        !           640:        read_file(fname, 1);
        !           641: }
        !           642: 
        !           643: #include "temp.h"
        !           644: 
        !           645: int    DOLsave = 0;    /* Do Lsave flag.  If lines aren't being save
        !           646:                           when you think they should have been, this
        !           647:                           flag is probably not being set, or is being
        !           648:                           cleared before lsave() was called. */
        !           649: 
        !           650: int    nleft,          /* Number of good characters left in current block */
        !           651:        tmpfd;
        !           652: disk_line      tline;  /* Pointer to end of tmp file */
        !           653: 
        !           654: char   *tfname;
        !           655: 
        !           656: tmpinit()
        !           657: {
        !           658:        tfname = mktemp(TMPFILE);
        !           659:        (void) close(creat(tfname, 0600));
        !           660:        tmpfd = open(tfname, 2);
        !           661:        if (tmpfd == -1) {
        !           662:                printf("%s?\n", tfname);
        !           663:                finish(0);
        !           664:        }
        !           665:        block_init();
        !           666:        tline = 2;
        !           667: }
        !           668: 
        !           669: tmpclose()
        !           670: {
        !           671:        (void) close(tmpfd);
        !           672:        tmpfd = -1;
        !           673:        (void) unlink(tfname);
        !           674: }
        !           675: 
        !           676: /* Get a line at `tl' in the tmp file into `buf' which should be LBSIZE
        !           677:    long. */
        !           678: 
        !           679: int    Jr_Len;         /* Length of Just Read Line. */
        !           680: 
        !           681: char *
        !           682: getline(tl, buf)
        !           683: disk_line      tl;
        !           684: char   *buf;
        !           685: {
        !           686:        register char   *bp,
        !           687:                        *lp;
        !           688:        register int    nl;
        !           689: 
        !           690:        lp = buf;
        !           691:        bp = getblock(tl, READ);
        !           692:        nl = nleft;
        !           693:        tl &= ~OFFMSK;
        !           694: 
        !           695:        while (*lp++ = *bp++) {
        !           696:                if (--nl == 0) {
        !           697:                        /* += INCRMT moves tl to the next block in
        !           698:                           the tmp file. */
        !           699:                        bp = getblock(tl += INCRMT, READ);
        !           700:                        nl = nleft;
        !           701:                }
        !           702:        }
        !           703:        Jr_Len = (lp - buf) - 1;
        !           704: 
        !           705:        return buf;
        !           706: }
        !           707: 
        !           708: /* Put `buf' and return the disk address */
        !           709: 
        !           710: int    nretries = 0;
        !           711: 
        !           712: disk_line
        !           713: putline(buf)
        !           714: char   *buf;
        !           715: {
        !           716:        register char   *bp,
        !           717:                        *lp;
        !           718:        register int    nl;
        !           719:        disk_line       tl;
        !           720: 
        !           721:        lp = buf;
        !           722:        tl = tline;
        !           723:        bp = getblock(tl, WRITE);
        !           724:        nl = nleft;
        !           725:        tl &= ~OFFMSK;
        !           726:        while (*bp = *lp++) {
        !           727:                if (*bp++ == '\n') {
        !           728:                        *--bp = 0;
        !           729:                        break;
        !           730:                }
        !           731:                if (--nl == 0) {
        !           732:                        tline = (tl += INCRMT);
        !           733:                        bp = getblock(tl, WRITE);
        !           734:                        lp = buf;       /* start over ... */
        !           735:                        nretries++;
        !           736:                        nl = nleft;
        !           737:                }
        !           738:        }
        !           739:        tl = tline;
        !           740:        tline += (((lp - buf) + BNDRY - 1) >> SHFT) & 077776;
        !           741: 
        !           742:        return tl;
        !           743: }
        !           744: 
        !           745: typedef struct block {
        !           746:        short   b_dirty,
        !           747:                b_bno;
        !           748:        char    b_buf[BUFSIZ];
        !           749:        struct block
        !           750:                *b_LRUnext,
        !           751:                *b_LRUprev,
        !           752:                *b_HASHnext;
        !           753: } Block;
        !           754: 
        !           755: #define HASHSIZE       7       /* Primes work best (so I'm told) */
        !           756: #define B_HASH(bno)    (bno % HASHSIZE)
        !           757: 
        !           758: private Block  b_cache[NBUF],
        !           759:                *bht[HASHSIZE] = {0},           /* Block hash table */
        !           760:                *f_block = 0,
        !           761:                *l_block = 0;
        !           762: private int    max_bno = -1,
        !           763:                NBlocks;
        !           764: 
        !           765: private
        !           766: block_init()
        !           767: {
        !           768:        register Block  *bp,    /* Block pointer */
        !           769:                        **hp;   /* Hash pointer */
        !           770:        register short  bno;
        !           771: 
        !           772:        for (bp = b_cache, bno = NBUF; --bno >= 0; bp++) {
        !           773:                NBlocks++;
        !           774:                bp->b_dirty = 0;
        !           775:                bp->b_bno = bno;
        !           776:                if (l_block == 0)
        !           777:                        l_block = bp;
        !           778:                bp->b_LRUprev = 0;
        !           779:                bp->b_LRUnext = f_block;
        !           780:                if (f_block != 0)
        !           781:                        f_block->b_LRUprev = bp;
        !           782:                f_block = bp;
        !           783: 
        !           784:                bp->b_HASHnext = *(hp = &bht[B_HASH(bno)]);
        !           785:                *hp = bp;
        !           786:        }
        !           787: }
        !           788: 
        !           789: private Block *
        !           790: lookup(bno)
        !           791: register short bno;
        !           792: {
        !           793:        register Block  *bp;
        !           794: 
        !           795:        for (bp = bht[B_HASH(bno)]; bp != 0; bp = bp->b_HASHnext)
        !           796:                if (bp->b_bno == bno)
        !           797:                        break;
        !           798:        return bp;
        !           799: }
        !           800: 
        !           801: private
        !           802: LRUunlink(b)
        !           803: register Block *b;
        !           804: {
        !           805:        if (b->b_LRUprev == 0)
        !           806:                f_block = b->b_LRUnext;
        !           807:        else
        !           808:                b->b_LRUprev->b_LRUnext = b->b_LRUnext;
        !           809:        if (b->b_LRUnext == 0)
        !           810:                l_block = b->b_LRUprev;
        !           811:        else
        !           812:                b->b_LRUnext->b_LRUprev = b->b_LRUprev;
        !           813: }
        !           814: 
        !           815: private Block *
        !           816: b_unlink(bp)
        !           817: register Block *bp;
        !           818: {
        !           819:        register Block  *hp,
        !           820:                        *prev = 0;
        !           821: 
        !           822:        LRUunlink(bp);
        !           823:        /* Now that we have the block, we remove it from its position
        !           824:           in the hash table, so we can THEN put it somewhere else with
        !           825:           it's new block assignment. */
        !           826: 
        !           827:        for (hp = bht[B_HASH(bp->b_bno)]; hp != 0; prev = hp, hp = hp->b_HASHnext)
        !           828:                if (hp == bp)
        !           829:                        break;
        !           830:        if (hp == 0) {
        !           831:                printf("\rBlock %d missing!", bp->b_bno);
        !           832:                finish(0);
        !           833:        }
        !           834:        if (prev)
        !           835:                prev->b_HASHnext = hp->b_HASHnext;
        !           836:        else
        !           837:                bht[B_HASH(bp->b_bno)] = hp->b_HASHnext;
        !           838: 
        !           839:        if (bp->b_dirty) {      /* Do, now, the delayed write */
        !           840:                blkio(bp, write);
        !           841:                bp->b_dirty = 0;
        !           842:        }
        !           843: 
        !           844:        return bp;
        !           845: }
        !           846: 
        !           847: /* Get a block which contains at least part of the line with the address
        !           848:    atl.  Returns a pointer to the block and sets the global variable
        !           849:    nleft (number of good characters left in the buffer). */
        !           850: 
        !           851: char *
        !           852: getblock(atl, iof)
        !           853: disk_line      atl;
        !           854: {
        !           855:        register int    bno,
        !           856:                        off;
        !           857:        register Block  *bp;
        !           858:        static Block    *lastb = 0;
        !           859: 
        !           860:        bno = (atl >> OFFBTS) & BLKMSK;
        !           861:        off = (atl << SHFT) & LBTMSK;
        !           862:        if (bno >= NMBLKS)
        !           863:                error("Tmp file too large.  Get help!");
        !           864:        nleft = BUFSIZ - off;
        !           865:        if (lastb != 0 && lastb->b_bno == bno)
        !           866:                return lastb->b_buf + off;
        !           867: 
        !           868:        /* The requested block already lives in memory, so we move
        !           869:           it to the end of the LRU list (making it Most Recently Used)
        !           870:           and then return a pointer to it. */
        !           871: 
        !           872:        if (bp = lookup(bno)) {
        !           873:                if (bp != l_block) {
        !           874:                        LRUunlink(bp);
        !           875:                        if (l_block == 0)
        !           876:                                f_block = l_block = bp;
        !           877:                        else
        !           878:                                l_block->b_LRUnext = bp;
        !           879:                        bp->b_LRUprev = l_block;
        !           880:                        l_block = bp;
        !           881:                        bp->b_LRUnext = 0;
        !           882:                }
        !           883:                if (bp->b_bno > max_bno)
        !           884:                        max_bno = bp->b_bno;
        !           885:                bp->b_dirty |= iof;
        !           886:                lastb = bp;
        !           887:                return bp->b_buf + off;
        !           888:        }
        !           889: 
        !           890:        /* The block we want doesn't reside in memory so we take the
        !           891:           least recently used clean block (if there is one) and use
        !           892:           it.  */
        !           893: 
        !           894:        bp = f_block;
        !           895:        if (bp->b_dirty)        /* The best block is dirty ... */
        !           896:                SyncTmp();
        !           897: 
        !           898:        bp = b_unlink(bp);
        !           899:        if (l_block == 0)
        !           900:                l_block = f_block = bp;
        !           901:        else
        !           902:                l_block->b_LRUnext = bp;        /* Place it at the end ... */
        !           903:        bp->b_LRUprev = l_block;
        !           904:        l_block = bp;
        !           905:        bp->b_LRUnext = 0;              /* so it's Most Recently Used */
        !           906: 
        !           907:        bp->b_dirty = iof;
        !           908:        bp->b_bno = bno;
        !           909:        bp->b_HASHnext = bht[B_HASH(bno)];
        !           910:        bht[B_HASH(bno)] = bp;
        !           911: 
        !           912:        /* Get the current contents of the block UNLESS this is a new
        !           913:           block that's never been looked at before, i.e., it's past
        !           914:           the end of the tmp file. */
        !           915: 
        !           916:        if (bp->b_bno <= max_bno)
        !           917:                blkio(bp, read);
        !           918:        else
        !           919:                max_bno = bno;
        !           920: 
        !           921:        lastb = bp;
        !           922:        return bp->b_buf + off;
        !           923: }
        !           924: 
        !           925: char *
        !           926: lbptr(line)
        !           927: Line   *line;
        !           928: {
        !           929:        return getblock(line->l_dline, READ);
        !           930: }
        !           931: 
        !           932: private
        !           933: blkio(b, iofcn)
        !           934: register Block *b;
        !           935: register int   (*iofcn)();
        !           936: {
        !           937:        (void) lseek(tmpfd, (long) ((unsigned) b->b_bno) * BUFSIZ, 0);
        !           938:        if ((*iofcn)(tmpfd, b->b_buf, BUFSIZ) != BUFSIZ)
        !           939:                error("Tmp file %s error.", (iofcn == read) ? "read" : "write");
        !           940: }
        !           941: 
        !           942: SyncTmp()
        !           943: {
        !           944:        register Block  *b;
        !           945: 
        !           946:        for (b = f_block; b != 0; b = b->b_LRUnext)
        !           947:                if (b->b_dirty) {
        !           948:                        blkio(b, write);
        !           949:                        b->b_dirty = 0;
        !           950:                }
        !           951: }
        !           952: 
        !           953: /* save the current contents of linebuf, if it has changed */
        !           954: 
        !           955: lsave()
        !           956: {
        !           957:        if (curbuf == 0 || !DOLsave)    /* Nothing modified recently */
        !           958:                return;
        !           959: 
        !           960:        if (strcmp(lbptr(curline), linebuf) != 0)
        !           961:                SavLine(curline, linebuf);      /* Put linebuf on the disk. */
        !           962:        DOLsave = 0;
        !           963: }
        !           964: 
        !           965: #ifdef BACKUPFILES
        !           966: file_backup(fname)
        !           967: char *fname;
        !           968: {
        !           969:        char *s;
        !           970:        register int    i;
        !           971:        int     fd1,
        !           972:                fd2;
        !           973:        char    tmp1[BUFSIZ],
        !           974:                tmp2[BUFSIZ];
        !           975:        
        !           976:        strcpy(tmp1, fname);
        !           977:        
        !           978:        if ((s = rindex(tmp1, '/')) == NULL)
        !           979:                sprintf(tmp2, "#%s", fname);
        !           980:        else {
        !           981:                *s++ = NULL;
        !           982:                sprintf(tmp2, "%s/#%s", tmp1, s);
        !           983:        }
        !           984: 
        !           985:        if ((fd1 = open(fname, 0)) < 0)
        !           986:                return;
        !           987: 
        !           988:        if ((fd2 = creat(tmp2, CreatMode)) < 0) {
        !           989:                (void) close(fd1);
        !           990:                return;
        !           991:        }
        !           992: 
        !           993:        while ((i = read(fd1, tmp1, sizeof(tmp1))) > 0)
        !           994:                write(fd2, tmp1, i);
        !           995: 
        !           996: #ifdef BSD4_2
        !           997:        (void) fsync(fd2);
        !           998: #endif
        !           999:        (void) close(fd2);
        !          1000:        (void) close(fd1);
        !          1001: }
        !          1002: #endif

unix.superglobalmegacorp.com

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