# 2.11BSD#431 - /usr/src/new/jove/io.c

##### Functions

    AppReg            X
    Chdir             X
    Dchdir            X
    DoWriteReg        X
    InsFile           X
    LRUunlink         X
    PathParse         X
    Popd              X
    Pushd             X
    ReadFile          X
    SaveFile          X
    SyncTmp           X
    WriteFile         X
    WrtReg            X
    abspath           X
    b_unlink          X
    chk_mtime         X
    close_file        X
    d_cache_init      X
    dbackup           X
    dfollow           X
    dofread           X
    f_getputl         X
    fake_blkio        X
    file_backup       X
    file_write        X
    filemunge         X
    fixpath           X
    getCWD            X
    get_hdir          X
    getblock          X
    getline           X
    getwd             X
    lbptr             X
    lookup            X
    lsave             X
    make_cache        X
    open_file         X
    prCWD             X
    prDIRS            X
    pr_name           X
    putline           X
    putreg            X
    pwd               X
    read_file         X
    real_blkio        X
    setCWD            X
    tmpclose          X
    tmpinit           X

##### Variables

    BkupOnWrite       X
    CreatMode         X
    DFree             X
    DOLsave           X
    DirSP             X
    DirStack          X
    EndWNewline       X
    HomeDir           X
    HomeLen           X
    Jr_Len            X
    OkayBadChars      X
    b_cache           X
    bht               X
    genbuf            X
    io_chars          X
    io_lines          X
    iobuff            X
    linebuf           X
    max_bno           X
    nleft             X
    private           X
    tfname            X
    tmpfd             X

##### Macros

    B_HASH            X
    F_OK              X
    HASHSIZE          X
    NDIRS             X
    PWD               X
    W_OK              X
    lockblock         X
    private           X
    unlockblock       X

##### struct's

    block             X

##### typedef's

    Block             X

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

#### Defined functions

AppReg defined in line 650; used 4 times

- in /usr/src/new/jove/externs.h line 186, 794
- in /usr/src/new/jove/funcdefs.c line 22, 280

Chdir defined in line 309; used 2 times

- in /usr/src/new/jove/funcdefs.c line 57, 312

Dchdir defined in line 1438; used 8 times

- in line 66, 92, 319, 426, 432, 457, 1483-1485(2)

DoWriteReg defined in line 658; used 4 times

- in line 647, 653
- in /usr/src/new/jove/externs.h line 269, 877

InsFile defined in line 898; used 4 times

- in /usr/src/new/jove/externs.h line 308, 916
- in /usr/src/new/jove/funcdefs.c line 120, 416

LRUunlink defined in line 1228; used 4 times

- in line 61, 87, 1249, 1302

PathParse defined in line 578; used 9 times

- in /usr/src/new/jove/ask.c line 397, 486, 566
- in /usr/src/new/jove/buf.c line 528, 595
- in /usr/src/new/jove/externs.h line 339, 947
- in /usr/src/new/jove/mac.c line 1656, 1686

Popd defined in line 448; used 2 times

- in /usr/src/new/jove/funcdefs.c line 61, 471

Pushd defined in line 404; used 2 times

- in /usr/src/new/jove/funcdefs.c line 60, 492

ReadFile defined in line 851; used 4 times

- in /usr/src/new/jove/externs.h line 356, 964
- in /usr/src/new/jove/funcdefs.c line 174, 571

SaveFile defined in line 229; used 6 times

- in line 882
- in /usr/src/new/jove/buf.c line 370
- in /usr/src/new/jove/externs.h line 371, 979
- in /usr/src/new/jove/funcdefs.c line 206, 509

SyncTmp defined in line 1192; used 4 times

- in line 1323
- in /usr/src/new/jove/externs.h line 391, 999
- in /usr/src/new/jove/rec.c line 143

WriteFile defined in line 688; used 5 times

- in line 234
- in /usr/src/new/jove/externs.h line 415, 1023
- in /usr/src/new/jove/funcdefs.c line 208, 577

WrtReg defined in line 644; used 4 times

- in /usr/src/new/jove/externs.h line 417, 1025
- in /usr/src/new/jove/funcdefs.c line 210, 580

abspath defined in line 1472; used 3 times

- in line 58, 84, 493

b_unlink defined in line 1242; used 3 times

- in line 46, 72, 1325

chk_mtime defined in line 791; used 4 times

- in line 238, 722, 867
- in /usr/src/new/jove/misc.c line 269

close_file defined in line 125; used 9 times

- in line 203, 568, 683, 847
- in /usr/src/new/jove/externs.h line 432, 1040
- in /usr/src/new/jove/macros.c line 284
- in /usr/src/new/jove/proc.c line 702
- in /usr/src/new/jove/re1.c line 298

d_cache_init defined in line 1167; used 3 times

- in /usr/src/new/jove/externs.h line 437, 1045
- in /usr/src/new/jove/jove.c line 1202

dbackup defined in line 464; used 3 times

- in line 50, 76, 510

dfollow defined in line 475; used 3 times

- in line 68, 94, 613

dofread defined in line 206; used 3 times

- in line 196
- in /usr/src/new/jove/externs.h line 447, 1055

f_getputl defined in line 1026; used 4 times

- in line 214, 221
- in /usr/src/new/jove/externs.h line 119, 726

fake_blkio defined in line 1157; used 3 times

- in line 60, 86, 1189

file_backup defined in line 1373; used 4 times

- in line 674, 832
- in /usr/src/new/jove/externs.h line 457, 1065

file_write defined in line 824; used 6 times

- in line 240, 728
- in /usr/src/new/jove/abbrev.c line 304
- in /usr/src/new/jove/externs.h line 458, 1066
- in /usr/src/new/jove/misc.c line 271

filemunge defined in line 619; used 7 times

- in line 236, 671, 678, 725
- in /usr/src/new/jove/externs.h line 459, 1067
- in /usr/src/new/jove/misc.c line 267

fixpath defined in line 1457; used 7 times

- in line 52, 78, 384, 1480, 1488-1492(2), 1501

getCWD defined in line 366; used 3 times

- in /usr/src/new/jove/jove.c line 459, 1228
- in /usr/src/new/jove/proc.c line 719

get_hdir defined in line 551; used 1 times

- in line 602

getblock defined in line 1278; used 10 times

- in line 54, 80, 964-966(2), 977, 996, 1007, 1042, 1069, 1356

getline defined in line 968; never used
getwd defined in line 336; used 2 times

- in line 371, 382

lbptr defined in line 1352; used 8 times

- in line 1367
- in /usr/src/new/jove/c.c line 128
- in /usr/src/new/jove/externs.h line 45, 652
- in /usr/src/new/jove/re.c line 601, 726-730(2)
- in /usr/src/new/jove/util.c line 428

lookup defined in line 1216; used 5 times

- in line 47, 73, 1198-1202(2), 1300

lsave defined in line 1361; used 11 times

- in /usr/src/new/jove/buf.c line 689
- in /usr/src/new/jove/externs.h line 491, 1099
- in /usr/src/new/jove/insert.c line 413
- in /usr/src/new/jove/jove.c line 132
- in /usr/src/new/jove/misc.c line 89, 229
- in /usr/src/new/jove/re.c line 707
- in /usr/src/new/jove/re1.c line 63
- in /usr/src/new/jove/rec.c line 142
- in /usr/src/new/jove/util.c line 246

make_cache defined in line 1131; used 1 times

- in /usr/src/new/jove/jove.c line 1167

open_file defined in line 748; used 14 times

- in line 187, 562, 681, 835
- in /usr/src/new/jove/abbrev.c line 203, 229
- in /usr/src/new/jove/extend.c line 308, 994
- in /usr/src/new/jove/externs.h line 125, 732
- in /usr/src/new/jove/io.h line 40
- in /usr/src/new/jove/macros.c line 274
- in /usr/src/new/jove/proc.c line 755
- in /usr/src/new/jove/re1.c line 235

prCWD defined in line 399; used 3 times

- in line 329
- in /usr/src/new/jove/funcdefs.c line 58, 493

prDIRS defined in line 390; used 4 times

- in line 445, 461
- in /usr/src/new/jove/funcdefs.c line 59, 359

pr_name defined in line 283; used 14 times

- in line 396, 759, 767-772(2), 803-808(2)
- in /usr/src/new/jove/ask.c line 554
- in /usr/src/new/jove/buf.c line 614
- in /usr/src/new/jove/disp.c line 1016, 1041
- in /usr/src/new/jove/extend.c line 1008
- in /usr/src/new/jove/externs.h line 48, 655
- in /usr/src/new/jove/util.c line 374

putline defined in line 985; used 7 times

- in /usr/src/new/jove/delete.c line 58, 67
- in /usr/src/new/jove/externs.h line 120, 727
- in /usr/src/new/jove/insert.c line 424, 440
- in /usr/src/new/jove/jove.h line 111

putreg defined in line 143; used 5 times

- in line 682, 846
- in /usr/src/new/jove/externs.h line 519, 1125
- in /usr/src/new/jove/proc.c line 763

pwd defined in line 277; used 4 times

- in /usr/src/new/jove/disp.c line 908, 1016
- in /usr/src/new/jove/externs.h line 581, 625

read_file defined in line 177; used 6 times

- in line 894, 910
- in /usr/src/new/jove/abbrev.c line 297
- in /usr/src/new/jove/buf.c line 696
- in /usr/src/new/jove/externs.h line 523, 1129

real_blkio defined in line 1139; used 4 times

- in line 62, 88, 1163-1164(2)

setCWD defined in line 353; used 5 times

- in line 328, 387, 443
- in /usr/src/new/jove/jove.c line 1226
- in /usr/src/new/jove/mac.c line 1635

tmpclose defined in line 948; used 3 times

- in /usr/src/new/jove/externs.h line 543, 1149
- in /usr/src/new/jove/jove.c line 147

tmpinit defined in line 926; used 3 times

- in line 1162
- in /usr/src/new/jove/externs.h line 544, 1150

#### Defined variables

BkupOnWrite defined in line 122; used 3 times

- in line 673, 831
- in /usr/src/new/jove/vars.c line 58

CreatMode defined in line 656; used 2 times

- in line 1401
- in /usr/src/new/jove/vars.c line 43

DFree defined in line 922; used 8 times

- in line 995, 1006, 1012-1013(2), 1041, 1067, 1079-1080(2)

DOLsave defined in line 915; used 2 times

- in line 1364-1369(2)

DirSP defined in line 274; used 10 times

- in line 275, 395, 420-424(4), 440-442(2), 450-455(2)

DirStack defined in line 273; used 5 times

- in line 275, 396, 423-424(3)

EndWNewline defined in line 141; used 2 times

- in line 837
- in /usr/src/new/jove/vars.c line 44

HomeDir defined in line 247; used 6 times

- in line 259, 297(2), 590, 932
- in /usr/src/new/jove/rec.c line 31

HomeLen defined in line 248; used 4 times

- in line 259-262(2), 297-300(2)

Jr_Len defined in line 961; used 2 times

- in line 980
- in /usr/src/new/jove/util.c line 439

OkayBadChars defined in line 686; used 2 times

- in line 702
- in /usr/src/new/jove/vars.c line 17

b_cache defined in line 1112; used 2 times

- in line 1133, 1174

bht defined in line 1114; used 6 times

- in line 1186, 1222, 1254, 1264, 1336-1337(2)

genbuf defined in line 117; used 6 times

- in line 564-566(3)
- in /usr/src/new/jove/proc.c line 668-677(3)

io_chars defined in line 108; used 6 times

- in line 133, 158-165(3), 197, 756

io_lines defined in line 109; used 4 times

- in line 132, 164, 757, 1092

iobuff defined in line 116; used 10 times

- in line 187, 681, 835
- in /usr/src/new/jove/macros.c line 274
- in /usr/src/new/jove/proc.c line 638, 662, 755, 761
- in /usr/src/new/jove/re1.c line 235
- in /usr/src/new/jove/rec.c line 43

linebuf defined in line 118; used 58 times

- in line 216-218(3), 224-225(3), 347, 1367-1368(2)
- in /usr/src/new/jove/jove.h line 116-118(2)
- in /usr/src/new/jove/misc.c line 37-38(2), 74, 128, 283-286(2), 517, 523
- in /usr/src/new/jove/move.c line 116, 159, 208, 219-221(2), 273, 293
- in /usr/src/new/jove/paragraph.c line 170-179(4), 185, 404-406(2), 418-423(2), 461, 469-473(2)
- in /usr/src/new/jove/proc.c line 392
- in /usr/src/new/jove/re.c line 952-953(2)
- in /usr/src/new/jove/re1.c line 89-94(2), 137, 148, 359-366(4), 408
- in /usr/src/new/jove/util.c line 331, 341, 426, 437-439(3)
- in /usr/src/new/jove/wind.c line 175-176(2)

max_bno defined in line 1117; used 5 times

- in line 1201, 1311-1312(2), 1343-1346(2)

nleft defined in line 920; used 5 times

- in line 997, 1009, 1043, 1070, 1291

private defined in line 1216; never used
tfname defined in line 924; used 7 times

- in line 936-942(6), 955

tmpfd defined in line 921; used 8 times

- in line 940-944(3), 951-954(3), 1152-1153(2)

#### Defined struct's

block defined in line 1096; used 8 times

- in line 45-46(2), 60-62(3), 71, 1100(2)

#### Defined typedef's

Block defined in line 1104; used 18 times

- in line 1110-1112(2), 1141, 1159, 1216, 1230, 1242-1124(3), 1133(2), 1170, 1195-1198(2), 1220, 1246, 1284-1285(2)

#### Defined macros

B_HASH defined in line 1107; used 6 times

- in line 1186, 1222, 1254, 1264, 1336-1337(2)

F_OK defined in line 105; never used
HASHSIZE defined in line 1106; used 2 times

- in line 1107, 1114

NDIRS defined in line 271; used 3 times

- in line 273, 440-441(2)

PWD defined in line 275; used 18 times

- in line 280, 291-293(2), 316, 356-363(5), 401, 422-428(3), 453-459(4), 491

W_OK defined in line 104; used 2 times

- in line 103, 767

lockblock defined in line 1023; used 1 times

- in line 1066

private defined in line 99; used 31 times

- in line 40-49(3), 56, 64, 71-75(2), 82, 90, 98, 273-274(2), 464, 475, 530, 551, 920-924(2), 966, 1110, 1117, 1124-1126(2), 1139, 1157, 1228, 1242, 1278, 1438, 1457, 1472

unlockblock defined in line 1024; used 1 times

- in line 1074

Last modified: 1988-08-11 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 3758 |