Annotation of 43BSDTahoe/new/jove/io.c, revision 1.1.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.