Home | History | Annotate | Line # | Download | only in common
exf.c revision 1.2
      1 /*	$NetBSD: exf.c,v 1.2 2013/11/22 15:52:05 christos Exp $ */
      2 /*-
      3  * Copyright (c) 1992, 1993, 1994
      4  *	The Regents of the University of California.  All rights reserved.
      5  * Copyright (c) 1992, 1993, 1994, 1995, 1996
      6  *	Keith Bostic.  All rights reserved.
      7  *
      8  * See the LICENSE file for redistribution information.
      9  */
     10 
     11 #include "config.h"
     12 
     13 #ifndef lint
     14 static const char sccsid[] = "Id: exf.c,v 10.72 2003/08/10 09:44:01 skimo Exp  (Berkeley) Date: 2003/08/10 09:44:01 ";
     15 #endif /* not lint */
     16 
     17 #include <sys/param.h>
     18 #include <sys/types.h>		/* XXX: param.h may not have included types.h */
     19 #include <sys/queue.h>
     20 #include <sys/stat.h>
     21 
     22 /*
     23  * We include <sys/file.h>, because the flock(2) and open(2) #defines
     24  * were found there on historical systems.  We also include <fcntl.h>
     25  * because the open(2) #defines are found there on newer systems.
     26  */
     27 #include <sys/file.h>
     28 
     29 #include <bitstring.h>
     30 #include <dirent.h>
     31 #include <errno.h>
     32 #include <fcntl.h>
     33 #include <limits.h>
     34 #include <stdio.h>
     35 #include <stdlib.h>
     36 #include <string.h>
     37 #include <unistd.h>
     38 #include <time.h>
     39 
     40 #include "common.h"
     41 #include "dbinternal.h"
     42 
     43 static int	file_backup __P((SCR *, const char *, const char *));
     44 static void	file_cinit __P((SCR *));
     45 static void	file_comment __P((SCR *));
     46 static int	file_spath __P((SCR *, FREF *, struct stat *, int *));
     47 
     48 /*
     49  * file_add --
     50  *	Insert a file name into the FREF list, if it doesn't already
     51  *	appear in it.
     52  *
     53  * !!!
     54  * The "if it doesn't already appear" changes vi's semantics slightly.  If
     55  * you do a "vi foo bar", and then execute "next bar baz", the edit of bar
     56  * will reflect the line/column of the previous edit session.  Historic nvi
     57  * did not do this.  The change is a logical extension of the change where
     58  * vi now remembers the last location in any file that it has ever edited,
     59  * not just the previously edited file.
     60  *
     61  * PUBLIC: FREF *file_add __P((SCR *, const char *));
     62  */
     63 FREF *
     64 file_add(SCR *sp, const char *name)
     65 {
     66 	GS *gp;
     67 	FREF *frp, *tfrp;
     68 
     69 	/*
     70 	 * Return it if it already exists.  Note that we test against the
     71 	 * user's name, whatever that happens to be, including if it's a
     72 	 * temporary file.
     73 	 *
     74 	 * If the user added a file but was unable to initialize it, there
     75 	 * can be file list entries where the name field is NULL.  Discard
     76 	 * them the next time we see them.
     77 	 */
     78 	gp = sp->gp;
     79 	if (name != NULL)
     80 		for (frp = gp->frefq.cqh_first;
     81 		    frp != (FREF *)(void *)&gp->frefq; frp = frp->q.cqe_next) {
     82 			if (frp->name == NULL) {
     83 				tfrp = frp->q.cqe_next;
     84 				CIRCLEQ_REMOVE(&gp->frefq, frp, q);
     85 				if (frp->name != NULL)
     86 					free(frp->name);
     87 				free(frp);
     88 				frp = tfrp;
     89 				continue;
     90 			}
     91 			if (!strcmp(frp->name, name))
     92 				return (frp);
     93 		}
     94 
     95 	/* Allocate and initialize the FREF structure. */
     96 	CALLOC(sp, frp, FREF *, 1, sizeof(FREF));
     97 	if (frp == NULL)
     98 		return (NULL);
     99 
    100 	/*
    101 	 * If no file name specified, or if the file name is a request
    102 	 * for something temporary, file_init() will allocate the file
    103 	 * name.  Temporary files are always ignored.
    104 	 */
    105 	if (name != NULL && strcmp(name, TEMPORARY_FILE_STRING) &&
    106 	    (frp->name = strdup(name)) == NULL) {
    107 		free(frp);
    108 		msgq(sp, M_SYSERR, NULL);
    109 		return (NULL);
    110 	}
    111 
    112 	/* Append into the chain of file names. */
    113 	CIRCLEQ_INSERT_TAIL(&gp->frefq, frp, q);
    114 
    115 	return (frp);
    116 }
    117 
    118 /*
    119  * file_init --
    120  *	Start editing a file, based on the FREF structure.  If successsful,
    121  *	let go of any previous file.  Don't release the previous file until
    122  *	absolutely sure we have the new one.
    123  *
    124  * PUBLIC: int file_init __P((SCR *, FREF *, char *, int));
    125  */
    126 int
    127 file_init(SCR *sp, FREF *frp, char *rcv_name, int flags)
    128 {
    129 	EXF *ep;
    130 	struct stat sb;
    131 	size_t psize;
    132 	int fd, exists, open_err, readonly;
    133 	char *oname = NULL, tname[MAXPATHLEN];
    134 
    135 	open_err = readonly = 0;
    136 
    137 	/*
    138 	 * If the file is a recovery file, let the recovery code handle it.
    139 	 * Clear the FR_RECOVER flag first -- the recovery code does set up,
    140 	 * and then calls us!  If the recovery call fails, it's probably
    141 	 * because the named file doesn't exist.  So, move boldly forward,
    142 	 * presuming that there's an error message the user will get to see.
    143 	 */
    144 	if (F_ISSET(frp, FR_RECOVER)) {
    145 		F_CLR(frp, FR_RECOVER);
    146 		return (rcv_read(sp, frp));
    147 	}
    148 
    149 	/*
    150 	 * Required FRP initialization; the only flag we keep is the
    151 	 * cursor information.
    152 	 */
    153 	F_CLR(frp, ~FR_CURSORSET);
    154 
    155 	/*
    156 	 * Scan the user's path to find the file that we're going to
    157 	 * try and open.
    158 	 */
    159 	if (file_spath(sp, frp, &sb, &exists))
    160 		return (1);
    161 
    162 	/*
    163 	 * Check whether we already have this file opened in some
    164 	 * other screen.
    165 	 */
    166 	if (exists) {
    167 		EXF *exfp;
    168 		for (exfp = sp->gp->exfq.cqh_first;
    169 		    exfp != (EXF *)&sp->gp->exfq; exfp = exfp->q.cqe_next) {
    170 			if (exfp->mdev == sb.st_dev &&
    171 			    exfp->minode == sb.st_ino &&
    172 			    (exfp != sp->ep || exfp->refcnt > 1)) {
    173 				ep = exfp;
    174 				oname = ep->rcv_path;
    175 				goto postinit;
    176 			}
    177 		}
    178 	}
    179 
    180 	/*
    181 	 * Required EXF initialization:
    182 	 *	Flush the line caches.
    183 	 *	Default recover mail file fd to -1.
    184 	 *	Set initial EXF flag bits.
    185 	 */
    186 	CALLOC_RET(sp, ep, EXF *, 1, sizeof(EXF));
    187 	CIRCLEQ_INIT(&ep->scrq);
    188 	sp->c_lno = ep->c_nlines = OOBLNO;
    189 	ep->fd = ep->rcv_fd = ep->fcntl_fd = -1;
    190 	F_SET(ep, F_FIRSTMODIFY);
    191 
    192 	/*
    193 	 * If no name or backing file, for whatever reason, create a backing
    194 	 * temporary file, saving the temp file name so we can later unlink
    195 	 * it.  If the user never named this file, copy the temporary file name
    196 	 * to the real name (we display that until the user renames it).
    197 	 */
    198 	oname = frp->name;
    199 	if (LF_ISSET(FS_OPENERR) || oname == NULL || !exists) {
    200 		if (opts_empty(sp, O_TMP_DIRECTORY, 0))
    201 			goto err;
    202 		(void)snprintf(tname, sizeof(tname),
    203 		    "%s/vi.XXXXXX", O_STR(sp, O_TMP_DIRECTORY));
    204 		if ((fd = mkstemp(tname)) == -1) {
    205 			msgq(sp, M_SYSERR,
    206 			    "237|Unable to create temporary file");
    207 			goto err;
    208 		}
    209 		(void)close(fd);
    210 
    211 		if (frp->name == NULL)
    212 			F_SET(frp, FR_TMPFILE);
    213 		if ((frp->tname = strdup(tname)) == NULL ||
    214 		    (frp->name == NULL &&
    215 		     (frp->name = strdup(tname)) == NULL)) {
    216 			if (frp->tname != NULL) {
    217 				free(frp->tname);
    218 			}
    219 			msgq(sp, M_SYSERR, NULL);
    220 			(void)unlink(tname);
    221 			goto err;
    222 		}
    223 		oname = frp->tname;
    224 		psize = 1024;
    225 		if (!LF_ISSET(FS_OPENERR))
    226 			F_SET(frp, FR_NEWFILE);
    227 
    228 		time(&ep->mtime);
    229 	} else {
    230 		/*
    231 		 * XXX
    232 		 * A seat of the pants calculation: try to keep the file in
    233 		 * 15 pages or less.  Don't use a page size larger than 10K
    234 		 * (vi should have good locality) or smaller than 1K.
    235 		 */
    236 		psize = ((sb.st_size / 15) + 1023) / 1024;
    237 		if (psize > 10)
    238 			psize = 10;
    239 		if (psize == 0)
    240 			psize = 1;
    241 		psize *= 1024;
    242 
    243 		F_SET(ep, F_DEVSET);
    244 		ep->mdev = sb.st_dev;
    245 		ep->minode = sb.st_ino;
    246 
    247 		ep->mtime = sb.st_mtime;
    248 
    249 		if (!S_ISREG(sb.st_mode))
    250 			msgq_str(sp, M_ERR, oname,
    251 			    "238|Warning: %s is not a regular file");
    252 	}
    253 
    254 	/* Set up recovery. */
    255 	if (rcv_name == NULL) {
    256 		/* ep->rcv_path NULL if rcv_tmp fails */
    257 		rcv_tmp(sp, ep, frp->name);
    258 	} else {
    259 		if ((ep->rcv_path = strdup(rcv_name)) == NULL) {
    260 			msgq(sp, M_SYSERR, NULL);
    261 			goto err;
    262 		}
    263 		F_SET(ep, F_MODIFIED);
    264 	}
    265 
    266 	if (db_init(sp, ep, rcv_name, oname, psize, &open_err)) {
    267 		if (open_err && !LF_ISSET(FS_OPENERR))
    268 			goto oerr;
    269 		goto err;
    270 	}
    271 
    272 	/*
    273 	 * Do the remaining things that can cause failure of the new file,
    274 	 * mark and logging initialization.
    275 	 */
    276 	if (mark_init(sp, ep) || log_init(sp, ep))
    277 		goto err;
    278 
    279 postinit:
    280 	/*
    281 	 * Set the alternate file name to be the file we're discarding.
    282 	 *
    283 	 * !!!
    284 	 * Temporary files can't become alternate files, so there's no file
    285 	 * name.  This matches historical practice, although it could only
    286 	 * happen in historical vi as the result of the initial command, i.e.
    287 	 * if vi was executed without a file name.
    288 	 */
    289 	if (LF_ISSET(FS_SETALT))
    290 		set_alt_name(sp, sp->frp == NULL ||
    291 		    F_ISSET(sp->frp, FR_TMPFILE) ? NULL : sp->frp->name);
    292 
    293 	/*
    294 	 * Close the previous file; if that fails, close the new one and run
    295 	 * for the border.
    296 	 *
    297 	 * !!!
    298 	 * There's a nasty special case.  If the user edits a temporary file,
    299 	 * and then does an ":e! %", we need to re-initialize the backing
    300 	 * file, but we can't change the name.  (It's worse -- we're dealing
    301 	 * with *names* here, we can't even detect that it happened.)  Set a
    302 	 * flag so that the file_end routine ignores the backing information
    303 	 * of the old file if it happens to be the same as the new one.
    304 	 *
    305 	 * !!!
    306 	 * Side-effect: after the call to file_end(), sp->frp may be NULL.
    307 	 */
    308 	if (sp->ep != NULL) {
    309 		F_SET(frp, FR_DONTDELETE);
    310 		if (file_end(sp, NULL, LF_ISSET(FS_FORCE))) {
    311 			(void)file_end(sp, ep, 1);
    312 			goto err;
    313 		}
    314 		sp->ep = NULL;
    315 		F_CLR(frp, FR_DONTDELETE);
    316 	}
    317 
    318 	/*
    319 	 * Lock the file; if it's a recovery file, it should already be
    320 	 * locked.  Note, we acquire the lock after the previous file
    321 	 * has been ended, so that we don't get an "already locked" error
    322 	 * for ":edit!".
    323 	 *
    324 	 * XXX
    325 	 * While the user can't interrupt us between the open and here,
    326 	 * there's a race between the dbopen() and the lock.  Not much
    327 	 * we can do about it.
    328 	 *
    329 	 * XXX
    330 	 * We don't make a big deal of not being able to lock the file.  As
    331 	 * locking rarely works over NFS, and often fails if the file was
    332 	 * mmap(2)'d, it's far too common to do anything like print an error
    333 	 * message, let alone make the file readonly.  At some future time,
    334 	 * when locking is a little more reliable, this should change to be
    335 	 * an error.
    336 	 */
    337 	if (rcv_name == NULL && ep->refcnt == 0) {
    338 		if ((ep->fd = open(oname, O_RDWR)) == -1)
    339 		    goto no_lock;
    340 
    341 		switch (file_lock(sp, oname, &ep->fcntl_fd, ep->fd, 1)) {
    342 		case LOCK_FAILED:
    343 no_lock:
    344 			F_SET(frp, FR_UNLOCKED);
    345 			break;
    346 		case LOCK_UNAVAIL:
    347 			readonly = 1;
    348 			msgq_str(sp, M_INFO, oname,
    349 			    "239|%s already locked, session is read-only");
    350 			break;
    351 		case LOCK_SUCCESS:
    352 			break;
    353 		}
    354 	}
    355 
    356 	/*
    357          * Historically, the readonly edit option was set per edit buffer in
    358          * vi, unless the -R command-line option was specified or the program
    359          * was executed as "view".  (Well, to be truthful, if the letter 'w'
    360          * occurred anywhere in the program name, but let's not get into that.)
    361 	 * So, the persistant readonly state has to be stored in the screen
    362 	 * structure, and the edit option value toggles with the contents of
    363 	 * the edit buffer.  If the persistant readonly flag is set, set the
    364 	 * readonly edit option.
    365 	 *
    366 	 * Otherwise, try and figure out if a file is readonly.  This is a
    367 	 * dangerous thing to do.  The kernel is the only arbiter of whether
    368 	 * or not a file is writeable, and the best that a user program can
    369 	 * do is guess.  Obvious loopholes are files that are on a file system
    370 	 * mounted readonly (access catches this one on a few systems), or
    371 	 * alternate protection mechanisms, ACL's for example, that we can't
    372 	 * portably check.  Lots of fun, and only here because users whined.
    373 	 *
    374 	 * !!!
    375 	 * Historic vi displayed the readonly message if none of the file
    376 	 * write bits were set, or if an an access(2) call on the path
    377 	 * failed.  This seems reasonable.  If the file is mode 444, root
    378 	 * users may want to know that the owner of the file did not expect
    379 	 * it to be written.
    380 	 *
    381 	 * Historic vi set the readonly bit if no write bits were set for
    382 	 * a file, even if the access call would have succeeded.  This makes
    383 	 * the superuser force the write even when vi expects that it will
    384 	 * succeed.  I'm less supportive of this semantic, but it's historic
    385 	 * practice and the conservative approach to vi'ing files as root.
    386 	 *
    387 	 * It would be nice if there was some way to update this when the user
    388 	 * does a "^Z; chmod ...".  The problem is that we'd first have to
    389 	 * distinguish between readonly bits set because of file permissions
    390 	 * and those set for other reasons.  That's not too hard, but deciding
    391 	 * when to reevaluate the permissions is trickier.  An alternative
    392 	 * might be to turn off the readonly bit if the user forces a write
    393 	 * and it succeeds.
    394 	 *
    395 	 * XXX
    396 	 * Access(2) doesn't consider the effective uid/gid values.  This
    397 	 * probably isn't a problem for vi when it's running standalone.
    398 	 */
    399 	if (readonly || F_ISSET(sp, SC_READONLY) ||
    400 	    (!F_ISSET(frp, FR_NEWFILE) &&
    401 	    (!(sb.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) ||
    402 	    access(frp->name, W_OK))))
    403 		O_SET(sp, O_READONLY);
    404 	else
    405 		O_CLR(sp, O_READONLY);
    406 
    407 	/* Switch... */
    408 	++ep->refcnt;
    409 	CIRCLEQ_INSERT_HEAD(&ep->scrq, sp, eq);
    410 	sp->ep = ep;
    411 	sp->frp = frp;
    412 
    413 	/* Set the initial cursor position, queue initial command. */
    414 	file_cinit(sp);
    415 
    416 	/* Report conversion errors again. */
    417 	F_CLR(sp, SC_CONV_ERROR);
    418 
    419 	/* Redraw the screen from scratch, schedule a welcome message. */
    420 	F_SET(sp, SC_SCR_REFORMAT | SC_STATUS);
    421 
    422 	if (frp->lno == OOBLNO)
    423 		F_SET(sp, SC_SCR_TOP);
    424 
    425 	/* Append into the chain of file structures. */
    426 	if (ep->refcnt == 1)
    427 		CIRCLEQ_INSERT_TAIL(&sp->gp->exfq, ep, q);
    428 
    429 	return (0);
    430 
    431 err:	if (frp->name != NULL) {
    432 		free(frp->name);
    433 		frp->name = NULL;
    434 	}
    435 	if (frp->tname != NULL) {
    436 		(void)unlink(frp->tname);
    437 		free(frp->tname);
    438 		frp->tname = NULL;
    439 	}
    440 
    441 oerr:	if (F_ISSET(ep, F_RCV_ON))
    442 		(void)unlink(ep->rcv_path);
    443 	if (ep->rcv_path != NULL) {
    444 		free(ep->rcv_path);
    445 		ep->rcv_path = NULL;
    446 	}
    447 	if (ep->db != NULL) {
    448 		(void)db_close(ep->db);
    449 		ep->db = NULL;
    450 	}
    451 	free(ep);
    452 
    453 	return (open_err && !LF_ISSET(FS_OPENERR) ?
    454 	    file_init(sp, frp, rcv_name, flags | FS_OPENERR) : 1);
    455 }
    456 
    457 /*
    458  * file_spath --
    459  *	Scan the user's path to find the file that we're going to
    460  *	try and open.
    461  */
    462 static int
    463 file_spath(SCR *sp, FREF *frp, struct stat *sbp, int *existsp)
    464 {
    465 	size_t len;
    466 	int found;
    467 	char *name, path[MAXPATHLEN];
    468 	const char *p, *t;
    469 
    470 	/*
    471 	 * If the name is NULL or an explicit reference (i.e., the first
    472 	 * component is . or ..) ignore the O_PATH option.
    473 	 */
    474 	name = frp->name;
    475 	if (name == NULL) {
    476 		*existsp = 0;
    477 		return (0);
    478 	}
    479 	if (name[0] == '/' || (name[0] == '.' &&
    480 	    (name[1] == '/' || (name[1] == '.' && name[2] == '/')))) {
    481 		*existsp = !stat(name, sbp);
    482 		return (0);
    483 	}
    484 
    485 	/* Try . */
    486 	if (!stat(name, sbp)) {
    487 		*existsp = 1;
    488 		return (0);
    489 	}
    490 
    491 	/* Try the O_PATH option values. */
    492 	for (found = 0, p = t = O_STR(sp, O_PATH);; ++p)
    493 		if (*p == ':' || *p == '\0') {
    494 			if (t < p - 1) {
    495 				len = snprintf(path, sizeof(path), "%.*s/%s",
    496 				    (int)(p - t), t, name);
    497 				if (!stat(path, sbp)) {
    498 					found = 1;
    499 					break;
    500 				}
    501 			}
    502 			t = p + 1;
    503 			if (*p == '\0')
    504 				break;
    505 		}
    506 
    507 	/* If we found it, build a new pathname and discard the old one. */
    508 	if (found) {
    509 		char *q;
    510 		MALLOC_RET(sp, q, char *, len + 1);
    511 		memcpy(q, path, len + 1);
    512 		free(frp->name);
    513 		frp->name = q;
    514 	}
    515 	*existsp = found;
    516 	return (0);
    517 }
    518 
    519 /*
    520  * file_cinit --
    521  *	Set up the initial cursor position.
    522  */
    523 static void
    524 file_cinit(SCR *sp)
    525 {
    526 	GS *gp;
    527 	MARK m;
    528 	size_t len;
    529 	int nb;
    530 	const CHAR_T *wp;
    531 	size_t wlen;
    532 
    533 	/* Set some basic defaults. */
    534 	sp->lno = 1;
    535 	sp->cno = 0;
    536 
    537 	/*
    538 	 * Historically, initial commands (the -c option) weren't executed
    539 	 * until a file was loaded, e.g. "vi +10 nofile", followed by an
    540 	 * :edit or :tag command, would execute the +10 on the file loaded
    541 	 * by the subsequent command, (assuming that it existed).  This
    542 	 * applied as well to files loaded using the tag commands, and we
    543 	 * follow that historic practice.  Also, all initial commands were
    544 	 * ex commands and were always executed on the last line of the file.
    545 	 *
    546 	 * Otherwise, if no initial command for this file:
    547 	 *    If in ex mode, move to the last line, first nonblank character.
    548 	 *    If the file has previously been edited, move to the last known
    549 	 *	  position, and check it for validity.
    550 	 *    Otherwise, move to the first line, first nonblank.
    551 	 *
    552 	 * This gets called by the file init code, because we may be in a
    553 	 * file of ex commands and we want to execute them from the right
    554 	 * location in the file.
    555 	 */
    556 	nb = 0;
    557 	gp = sp->gp;
    558 	if (gp->c_option != NULL && !F_ISSET(sp->frp, FR_NEWFILE)) {
    559 		if (db_last(sp, &sp->lno))
    560 			return;
    561 		if (sp->lno == 0) {
    562 			sp->lno = 1;
    563 			sp->cno = 0;
    564 		}
    565 		CHAR2INT(sp, gp->c_option, strlen(gp->c_option) + 1,
    566 			 wp, wlen);
    567 		if (ex_run_str(sp, "-c option", wp, wlen - 1, 1, 1))
    568 			return;
    569 		gp->c_option = NULL;
    570 	} else if (F_ISSET(sp, SC_EX)) {
    571 		if (db_last(sp, &sp->lno))
    572 			return;
    573 		if (sp->lno == 0) {
    574 			sp->lno = 1;
    575 			sp->cno = 0;
    576 			return;
    577 		}
    578 		nb = 1;
    579 	} else {
    580 		if (F_ISSET(sp->frp, FR_CURSORSET)) {
    581 			sp->lno = sp->frp->lno;
    582 			sp->cno = sp->frp->cno;
    583 
    584 			/* If returning to a file in vi, center the line. */
    585 			 F_SET(sp, SC_SCR_CENTER);
    586 		} else {
    587 			if (O_ISSET(sp, O_COMMENT))
    588 				file_comment(sp);
    589 			else
    590 				sp->lno = 1;
    591 			nb = 1;
    592 		}
    593 		if (db_get(sp, sp->lno, 0, NULL, &len)) {
    594 			sp->lno = 1;
    595 			sp->cno = 0;
    596 			return;
    597 		}
    598 		if (!nb && sp->cno > len)
    599 			nb = 1;
    600 	}
    601 	if (nb) {
    602 		sp->cno = 0;
    603 		(void)nonblank(sp, sp->lno, &sp->cno);
    604 	}
    605 
    606 	/*
    607 	 * !!!
    608 	 * The initial column is also the most attractive column.
    609 	 */
    610 	sp->rcm = sp->cno;
    611 
    612 	/*
    613 	 * !!!
    614 	 * Historically, vi initialized the absolute mark, but ex did not.
    615 	 * Which meant, that if the first command in ex mode was "visual",
    616 	 * or if an ex command was executed first (e.g. vi +10 file) vi was
    617 	 * entered without the mark being initialized.  For consistency, if
    618 	 * the file isn't empty, we initialize it for everyone, believing
    619 	 * that it can't hurt, and is generally useful.  Not initializing it
    620 	 * if the file is empty is historic practice, although it has always
    621 	 * been possible to set (and use) marks in empty vi files.
    622 	 */
    623 	m.lno = sp->lno;
    624 	m.cno = sp->cno;
    625 	(void)mark_set(sp, ABSMARK1, &m, 0);
    626 }
    627 
    628 /*
    629  * file_end --
    630  *	Stop editing a file.
    631  *
    632  * PUBLIC: int file_end __P((SCR *, EXF *, int));
    633  */
    634 int
    635 file_end(SCR *sp, EXF *ep, int force)
    636 {
    637 	FREF *frp;
    638 
    639 	/*
    640 	 * !!!
    641 	 * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
    642 	 * (If argument ep is NULL, use sp->ep.)
    643 	 *
    644 	 * If multiply referenced, just decrement the count and return.
    645 	 */
    646 	if (ep == NULL)
    647 		ep = sp->ep;
    648 	CIRCLEQ_REMOVE(&ep->scrq, sp, eq);
    649 	if (--ep->refcnt != 0)
    650 		return (0);
    651 
    652 	/*
    653 	 *
    654 	 * Clean up the FREF structure.
    655 	 *
    656 	 * Save the cursor location.
    657 	 *
    658 	 * XXX
    659 	 * It would be cleaner to do this somewhere else, but by the time
    660 	 * ex or vi knows that we're changing files it's already happened.
    661 	 */
    662 	frp = sp->frp;
    663 	frp->lno = sp->lno;
    664 	frp->cno = sp->cno;
    665 	F_SET(frp, FR_CURSORSET);
    666 
    667 	/*
    668 	 * We may no longer need the temporary backing file, so clean it
    669 	 * up.  We don't need the FREF structure either, if the file was
    670 	 * never named, so lose it.
    671 	 *
    672 	 * !!!
    673 	 * Re: FR_DONTDELETE, see the comment above in file_init().
    674 	 */
    675 	if (!F_ISSET(frp, FR_DONTDELETE) && frp->tname != NULL) {
    676 		if (unlink(frp->tname))
    677 			msgq_str(sp, M_SYSERR, frp->tname, "240|%s: remove");
    678 		free(frp->tname);
    679 		frp->tname = NULL;
    680 		if (F_ISSET(frp, FR_TMPFILE)) {
    681 			CIRCLEQ_REMOVE(&sp->gp->frefq, frp, q);
    682 			if (frp->name != NULL)
    683 				free(frp->name);
    684 			free(frp);
    685 		}
    686 		sp->frp = NULL;
    687 	}
    688 
    689 	/*
    690 	 * Clean up the EXF structure.
    691 	 *
    692 	 * Close the db structure.
    693 	 */
    694 	if (ep->db->close != NULL) {
    695 		if ((sp->db_error = db_close(ep->db)) != 0 &&
    696 		    !force) {
    697 			msgq_str(sp, M_DBERR, frp->name, "241|%s: close");
    698 			CIRCLEQ_INSERT_HEAD(&ep->scrq, sp, eq);
    699 			++ep->refcnt;
    700 			return (1);
    701 		}
    702 		ep->db = NULL;
    703 	}
    704 
    705 	/* COMMITTED TO THE CLOSE.  THERE'S NO GOING BACK... */
    706 
    707 	/* Stop logging. */
    708 	(void)log_end(sp, ep);
    709 
    710 	/* Free up any marks. */
    711 	(void)mark_end(sp, ep);
    712 
    713 	if (ep->env) {
    714 		DB_ENV *env;
    715 
    716 		db_env_close(ep->env, 0);
    717 		ep->env = 0;
    718 		if ((sp->db_error = db_env_create(&env, 0)))
    719 			msgq(sp, M_DBERR, "env_create");
    720 		if ((sp->db_error = db_env_remove(env, ep->env_path, 0)))
    721 			msgq(sp, M_DBERR, "env->remove");
    722 		if (ep->env_path != NULL && rmdir(ep->env_path))
    723 			msgq_str(sp, M_SYSERR, ep->env_path, "242|%s: remove");
    724 	}
    725 
    726 	/*
    727 	 * Delete recovery files, close the open descriptor, free recovery
    728 	 * memory.  See recover.c for a description of the protocol.
    729 	 *
    730 	 * XXX
    731 	 * Unlink backup file first, we can detect that the recovery file
    732 	 * doesn't reference anything when the user tries to recover it.
    733 	 * There's a race, here, obviously, but it's fairly small.
    734 	 */
    735 	if (!F_ISSET(ep, F_RCV_NORM)) {
    736 		if (ep->rcv_path != NULL && unlink(ep->rcv_path))
    737 			msgq_str(sp, M_SYSERR, ep->rcv_path, "242|%s: remove");
    738 		if (ep->rcv_mpath != NULL && unlink(ep->rcv_mpath))
    739 			msgq_str(sp, M_SYSERR, ep->rcv_mpath, "243|%s: remove");
    740 	}
    741 	CIRCLEQ_REMOVE(&sp->gp->exfq, ep, q);
    742 	if (ep->fd != -1)
    743 		(void)close(ep->fd);
    744 	if (ep->fcntl_fd != -1)
    745 		(void)close(ep->fcntl_fd);
    746 	if (ep->rcv_fd != -1)
    747 		(void)close(ep->rcv_fd);
    748 	if (ep->env_path != NULL)
    749 		free(ep->env_path);
    750 	if (ep->rcv_path != NULL) {
    751 		free(ep->rcv_path);
    752 		ep->rcv_path = NULL;
    753 	}
    754 	if (ep->rcv_mpath != NULL)
    755 		free(ep->rcv_mpath);
    756 
    757 	free(ep);
    758 	return (0);
    759 }
    760 
    761 /*
    762  * file_write --
    763  *	Write the file to disk.  Historic vi had fairly convoluted
    764  *	semantics for whether or not writes would happen.  That's
    765  *	why all the flags.
    766  *
    767  * PUBLIC: int file_write __P((SCR *, MARK *, MARK *, char *, int));
    768  */
    769 int
    770 file_write(SCR *sp, MARK *fm, MARK *tm, char *name, int flags)
    771 {
    772 	enum { NEWFILE, OLDFILE } mtype;
    773 	struct stat sb;
    774 	EXF *ep;
    775 	FILE *fp;
    776 	FREF *frp;
    777 	MARK from, to;
    778 	size_t len;
    779 	u_long nlno, nch;
    780 	int fd, nf, noname, oflags, rval;
    781 	char *p, *s, *t, buf[MAXPATHLEN + 64];
    782 	const char *msgstr;
    783 
    784 	ep = sp->ep;
    785 	frp = sp->frp;
    786 
    787 	/*
    788 	 * Writing '%', or naming the current file explicitly, has the
    789 	 * same semantics as writing without a name.
    790 	 */
    791 	if (name == NULL || !strcmp(name, frp->name)) {
    792 		noname = 1;
    793 		name = frp->name;
    794 	} else
    795 		noname = 0;
    796 
    797 	/* Can't write files marked read-only, unless forced. */
    798 	if (!LF_ISSET(FS_FORCE) && noname && O_ISSET(sp, O_READONLY)) {
    799 		msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ?
    800 		    "244|Read-only file, not written; use ! to override" :
    801 		    "245|Read-only file, not written");
    802 		return (1);
    803 	}
    804 
    805 	/* If not forced, not appending, and "writeany" not set ... */
    806 	if (!LF_ISSET(FS_FORCE | FS_APPEND) && !O_ISSET(sp, O_WRITEANY)) {
    807 		/* Don't overwrite anything but the original file. */
    808 		if ((!noname || F_ISSET(frp, FR_NAMECHANGE)) &&
    809 		    !stat(name, &sb)) {
    810 			msgq_str(sp, M_ERR, name,
    811 			    LF_ISSET(FS_POSSIBLE) ?
    812 			    "246|%s exists, not written; use ! to override" :
    813 			    "247|%s exists, not written");
    814 			return (1);
    815 		}
    816 
    817 		/*
    818 		 * Don't write part of any existing file.  Only test for the
    819 		 * original file, the previous test catches anything else.
    820 		 */
    821 		if (!LF_ISSET(FS_ALL) && noname && !stat(name, &sb)) {
    822 			msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ?
    823 			    "248|Partial file, not written; use ! to override" :
    824 			    "249|Partial file, not written");
    825 			return (1);
    826 		}
    827 	}
    828 
    829 	/*
    830 	 * Figure out if the file already exists -- if it doesn't, we display
    831 	 * the "new file" message.  The stat might not be necessary, but we
    832 	 * just repeat it because it's easier than hacking the previous tests.
    833 	 * The information is only used for the user message and modification
    834 	 * time test, so we can ignore the obvious race condition.
    835 	 *
    836 	 * One final test.  If we're not forcing or appending the current file,
    837 	 * and we have a saved modification time, object if the file changed
    838 	 * since we last edited or wrote it, and make them force it.
    839 	 */
    840 	if (stat(name, &sb))
    841 		mtype = NEWFILE;
    842 	else {
    843 		if (noname && !LF_ISSET(FS_FORCE | FS_APPEND) &&
    844 		    ((F_ISSET(ep, F_DEVSET) &&
    845 		    (sb.st_dev != ep->mdev || sb.st_ino != ep->minode)) ||
    846 		    sb.st_mtime != ep->mtime)) {
    847 			msgq_str(sp, M_ERR, name, LF_ISSET(FS_POSSIBLE) ?
    848 "250|%s: file modified more recently than this copy; use ! to override" :
    849 "251|%s: file modified more recently than this copy");
    850 			return (1);
    851 		}
    852 
    853 		mtype = OLDFILE;
    854 	}
    855 
    856 	/* Set flags to create, write, and either append or truncate. */
    857 	oflags = O_CREAT | O_WRONLY |
    858 	    (LF_ISSET(FS_APPEND) ? O_APPEND : O_TRUNC);
    859 
    860 	/* Backup the file if requested. */
    861 	if (!opts_empty(sp, O_BACKUP, 1) &&
    862 	    file_backup(sp, name, O_STR(sp, O_BACKUP)) && !LF_ISSET(FS_FORCE))
    863 		return (1);
    864 
    865 	/* Open the file. */
    866 	SIGBLOCK;
    867 	if ((fd = open(name, oflags,
    868 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) < 0) {
    869 		msgq_str(sp, M_SYSERR, name, "%s");
    870 		SIGUNBLOCK;
    871 		return (1);
    872 	}
    873 	SIGUNBLOCK;
    874 
    875 	/* Try and get a lock. */
    876 	if (!noname && file_lock(sp, NULL, NULL, fd, 0) == LOCK_UNAVAIL)
    877 		msgq_str(sp, M_ERR, name,
    878 		    "252|%s: write lock was unavailable");
    879 
    880 #if __linux__
    881 	/*
    882 	 * XXX
    883 	 * In libc 4.5.x, fdopen(fd, "w") clears the O_APPEND flag (if set).
    884 	 * This bug is fixed in libc 4.6.x.
    885 	 *
    886 	 * This code works around this problem for libc 4.5.x users.
    887 	 * Note that this code is harmless if you're using libc 4.6.x.
    888 	 */
    889 	if (LF_ISSET(FS_APPEND) && lseek(fd, (off_t)0, SEEK_END) < 0) {
    890 		msgq(sp, M_SYSERR, "%s", name);
    891 		return (1);
    892 	}
    893 #endif
    894 
    895 	/*
    896 	 * Use stdio for buffering.
    897 	 *
    898 	 * XXX
    899 	 * SVR4.2 requires the fdopen mode exactly match the original open
    900 	 * mode, i.e. you have to open with "a" if appending.
    901 	 */
    902 	if ((fp = fdopen(fd, LF_ISSET(FS_APPEND) ? "a" : "w")) == NULL) {
    903 		msgq_str(sp, M_SYSERR, name, "%s");
    904 		(void)close(fd);
    905 		return (1);
    906 	}
    907 
    908 	/* Build fake addresses, if necessary. */
    909 	if (fm == NULL) {
    910 		from.lno = 1;
    911 		from.cno = 0;
    912 		fm = &from;
    913 		if (db_last(sp, &to.lno))
    914 			return (1);
    915 		to.cno = 0;
    916 		tm = &to;
    917 	}
    918 
    919 	rval = ex_writefp(sp, name, fp, fm, tm, &nlno, &nch, 0);
    920 
    921 	/*
    922 	 * Save the new last modification time -- even if the write fails
    923 	 * we re-init the time.  That way the user can clean up the disk
    924 	 * and rewrite without having to force it.
    925 	 */
    926 	if (noname) {
    927 		if (stat(name, &sb))
    928 			time(&ep->mtime);
    929 		else {
    930 			F_SET(ep, F_DEVSET);
    931 			ep->mdev = sb.st_dev;
    932 			ep->minode = sb.st_ino;
    933 
    934 			ep->mtime = sb.st_mtime;
    935 		}
    936 	}
    937 
    938 	/*
    939 	 * If the write failed, complain loudly.  ex_writefp() has already
    940 	 * complained about the actual error, reinforce it if data was lost.
    941 	 */
    942 	if (rval) {
    943 		if (!LF_ISSET(FS_APPEND))
    944 			msgq_str(sp, M_ERR, name,
    945 			    "254|%s: WARNING: FILE TRUNCATED");
    946 		return (1);
    947 	}
    948 
    949 	/*
    950 	 * Once we've actually written the file, it doesn't matter that the
    951 	 * file name was changed -- if it was, we've already whacked it.
    952 	 */
    953 	F_CLR(frp, FR_NAMECHANGE);
    954 
    955 	/*
    956 	 * If wrote the entire file, and it wasn't by appending it to a file,
    957 	 * clear the modified bit.  If the file was written to the original
    958 	 * file name and the file is a temporary, set the "no exit" bit.  This
    959 	 * permits the user to write the file and use it in the context of the
    960 	 * filesystem, but still keeps them from discarding their changes by
    961 	 * exiting.
    962 	 */
    963 	if (LF_ISSET(FS_ALL) && !LF_ISSET(FS_APPEND)) {
    964 		F_CLR(ep, F_MODIFIED);
    965 		if (F_ISSET(frp, FR_TMPFILE)) {
    966 			if (noname)
    967 				F_SET(frp, FR_TMPEXIT);
    968 			else
    969 				F_CLR(frp, FR_TMPEXIT);
    970 		}
    971 	}
    972 
    973 	p = msg_print(sp, name, &nf);
    974 	switch (mtype) {
    975 	case NEWFILE:
    976 		msgstr = msg_cat(sp,
    977 		    "256|%s: new file: %lu lines, %lu characters", NULL);
    978 		len = snprintf(buf, sizeof(buf), msgstr, p, nlno, nch);
    979 		break;
    980 	case OLDFILE:
    981 		msgstr = msg_cat(sp, LF_ISSET(FS_APPEND) ?
    982 		    "315|%s: appended: %lu lines, %lu characters" :
    983 		    "257|%s: %lu lines, %lu characters", NULL);
    984 		len = snprintf(buf, sizeof(buf), msgstr, p, nlno, nch);
    985 		break;
    986 	default:
    987 		abort();
    988 	}
    989 
    990 	/*
    991 	 * There's a nasty problem with long path names.  Cscope and tags files
    992 	 * can result in long paths and vi will request a continuation key from
    993 	 * the user.  Unfortunately, the user has typed ahead, and chaos will
    994 	 * result.  If we assume that the characters in the filenames only take
    995 	 * a single screen column each, we can trim the filename.
    996 	 */
    997 	s = buf;
    998 	if (len >= sp->cols) {
    999 		for (s = buf, t = buf + strlen(p); s < t &&
   1000 		    (*s != '/' || len >= sp->cols - 3); ++s, --len);
   1001 		if (s == t)
   1002 			s = buf;
   1003 		else {
   1004 			*--s = '.';		/* Leading ellipses. */
   1005 			*--s = '.';
   1006 			*--s = '.';
   1007 		}
   1008 	}
   1009 	msgq(sp, M_INFO, "%s", s);
   1010 	if (nf)
   1011 		FREE_SPACE(sp, p, 0);
   1012 	return (0);
   1013 }
   1014 
   1015 /*
   1016  * file_backup --
   1017  *	Backup the about-to-be-written file.
   1018  *
   1019  * XXX
   1020  * We do the backup by copying the entire file.  It would be nice to do
   1021  * a rename instead, but: (1) both files may not fit and we want to fail
   1022  * before doing the rename; (2) the backup file may not be on the same
   1023  * disk partition as the file being written; (3) there may be optional
   1024  * file information (MACs, DACs, whatever) that we won't get right if we
   1025  * recreate the file.  So, let's not risk it.
   1026  */
   1027 static int
   1028 file_backup(SCR *sp, const char *name, const char *bname)
   1029 {
   1030 	struct dirent *dp;
   1031 	struct stat sb;
   1032 	DIR *dirp;
   1033 	EXCMD cmd;
   1034 	off_t off;
   1035 	size_t blen;
   1036 	int flags, maxnum, nr, num, nw, rfd, wfd, version;
   1037 	char *bp, *pct, *slash, *t, buf[8192];
   1038 	const char *p, *estr, *wfname;
   1039 	const CHAR_T *wp;
   1040 	size_t wlen;
   1041 	size_t nlen;
   1042 	char *d = NULL;
   1043 
   1044 	rfd = wfd = -1;
   1045 	estr = wfname = NULL;
   1046 	bp = NULL;
   1047 
   1048 	/*
   1049 	 * Open the current file for reading.  Do this first, so that
   1050 	 * we don't exec a shell before the most likely failure point.
   1051 	 * If it doesn't exist, it's okay, there's just nothing to back
   1052 	 * up.
   1053 	 */
   1054 	errno = 0;
   1055 	if ((rfd = open(name, O_RDONLY, 0)) < 0) {
   1056 		if (errno == ENOENT)
   1057 			return (0);
   1058 		estr = name;
   1059 		goto err;
   1060 	}
   1061 
   1062 	/*
   1063 	 * If the name starts with an 'N' character, add a version number
   1064 	 * to the name.  Strip the leading N from the string passed to the
   1065 	 * expansion routines, for no particular reason.  It would be nice
   1066 	 * to permit users to put the version number anywhere in the backup
   1067 	 * name, but there isn't a special character that we can use in the
   1068 	 * name, and giving a new character a special meaning leads to ugly
   1069 	 * hacks both here and in the supporting ex routines.
   1070 	 *
   1071 	 * Shell and file name expand the option's value.
   1072 	 */
   1073 	ex_cinit(sp, &cmd, 0, 0, 0, 0, 0);
   1074 	if (bname[0] == 'N') {
   1075 		version = 1;
   1076 		++bname;
   1077 	} else
   1078 		version = 0;
   1079 	CHAR2INT(sp, bname, strlen(bname) + 1, wp, wlen);
   1080 	if (argv_exp2(sp, &cmd, wp, wlen - 1))
   1081 		return (1);
   1082 
   1083 	/*
   1084 	 *  0 args: impossible.
   1085 	 *  1 args: use it.
   1086 	 * >1 args: object, too many args.
   1087 	 */
   1088 	if (cmd.argc != 1) {
   1089 		msgq_str(sp, M_ERR, bname,
   1090 		    "258|%s expanded into too many file names");
   1091 		(void)close(rfd);
   1092 		return (1);
   1093 	}
   1094 
   1095 	/*
   1096 	 * If appending a version number, read through the directory, looking
   1097 	 * for file names that match the name followed by a number.  Make all
   1098 	 * of the other % characters in name literal, so the user doesn't get
   1099 	 * surprised and sscanf doesn't drop core indirecting through pointers
   1100 	 * that don't exist.  If any such files are found, increment its number
   1101 	 * by one.
   1102 	 */
   1103 	if (version) {
   1104 		GET_SPACE_GOTOC(sp, bp, blen, cmd.argv[0]->len * 2 + 50);
   1105 		INT2SYS(sp, cmd.argv[0]->bp, cmd.argv[0]->len + 1,
   1106 			 p, nlen);
   1107 		d = strdup(p);
   1108 		p = d;
   1109 		for (t = bp, slash = NULL;
   1110 		     p[0] != '\0'; *t++ = *p++)
   1111 			if (p[0] == '%') {
   1112 				if (p[1] != '%')
   1113 					*t++ = '%';
   1114 			} else if (p[0] == '/')
   1115 				slash = t;
   1116 		pct = t;
   1117 		*t++ = '%';
   1118 		*t++ = 'd';
   1119 		*t = '\0';
   1120 
   1121 		if (slash == NULL) {
   1122 			dirp = opendir(".");
   1123 			p = bp;
   1124 		} else {
   1125 			*slash = '\0';
   1126 			dirp = opendir(bp);
   1127 			*slash = '/';
   1128 			p = slash + 1;
   1129 		}
   1130 		if (dirp == NULL) {
   1131 			INT2SYS(sp, cmd.argv[0]->bp, cmd.argv[0]->len + 1,
   1132 				estr, nlen);
   1133 			goto err;
   1134 		}
   1135 
   1136 		for (maxnum = 0; (dp = readdir(dirp)) != NULL;)
   1137 			if (sscanf(dp->d_name, p, &num) == 1 && num > maxnum)
   1138 				maxnum = num;
   1139 		(void)closedir(dirp);
   1140 
   1141 		/* Format the backup file name. */
   1142 		(void)snprintf(pct, blen - (pct - bp), "%d", maxnum + 1);
   1143 		wfname = bp;
   1144 	} else {
   1145 		bp = NULL;
   1146 		INT2SYS(sp, cmd.argv[0]->bp, cmd.argv[0]->len + 1,
   1147 			wfname, nlen);
   1148 	}
   1149 
   1150 	/* Open the backup file, avoiding lurkers. */
   1151 	if (stat(wfname, &sb) == 0) {
   1152 		if (!S_ISREG(sb.st_mode)) {
   1153 			msgq_str(sp, M_ERR, bname,
   1154 			    "259|%s: not a regular file");
   1155 			goto err;
   1156 		}
   1157 		if (sb.st_uid != getuid()) {
   1158 			msgq_str(sp, M_ERR, bname, "260|%s: not owned by you");
   1159 			goto err;
   1160 		}
   1161 		if (sb.st_mode & (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) {
   1162 			msgq_str(sp, M_ERR, bname,
   1163 			   "261|%s: accessible by a user other than the owner");
   1164 			goto err;
   1165 		}
   1166 		flags = O_TRUNC;
   1167 	} else
   1168 		flags = O_CREAT | O_EXCL;
   1169 	if ((wfd = open(wfname, flags | O_WRONLY, S_IRUSR | S_IWUSR)) < 0) {
   1170 		estr = bname;
   1171 		goto err;
   1172 	}
   1173 
   1174 	/* Copy the file's current contents to its backup value. */
   1175 	while ((nr = read(rfd, buf, sizeof(buf))) > 0)
   1176 		for (off = 0; nr != 0; nr -= nw, off += nw)
   1177 			if ((nw = write(wfd, buf + off, nr)) < 0) {
   1178 				estr = wfname;
   1179 				goto err;
   1180 			}
   1181 	if (nr < 0) {
   1182 		estr = name;
   1183 		goto err;
   1184 	}
   1185 
   1186 	if (close(rfd)) {
   1187 		estr = name;
   1188 		goto err;
   1189 	}
   1190 	if (close(wfd)) {
   1191 		estr = wfname;
   1192 		goto err;
   1193 	}
   1194 	if (bp != NULL)
   1195 		FREE_SPACE(sp, bp, blen);
   1196 	if (d != NULL)
   1197 		free(d);
   1198 	return (0);
   1199 
   1200 alloc_err:
   1201 err:	if (rfd != -1)
   1202 		(void)close(rfd);
   1203 	if (wfd != -1) {
   1204 		(void)unlink(wfname);
   1205 		(void)close(wfd);
   1206 	}
   1207 	if (estr)
   1208 		msgq_str(sp, M_SYSERR, estr, "%s");
   1209 	if (d != NULL)
   1210 		free(d);
   1211 	if (bp != NULL)
   1212 		FREE_SPACE(sp, bp, blen);
   1213 	return (1);
   1214 }
   1215 
   1216 /*
   1217  * file_comment --
   1218  *	Skip the first comment.
   1219  */
   1220 static void
   1221 file_comment(SCR *sp)
   1222 {
   1223 	db_recno_t lno;
   1224 	size_t len;
   1225 	CHAR_T *p;
   1226 
   1227 	for (lno = 1; !db_get(sp, lno, 0, &p, &len) && len == 0; ++lno);
   1228 	if (p == NULL)
   1229 		return;
   1230 	if (p[0] == '#') {
   1231 		F_SET(sp, SC_SCR_TOP);
   1232 		while (!db_get(sp, ++lno, 0, &p, &len))
   1233 			if (len < 1 || p[0] != '#') {
   1234 				sp->lno = lno;
   1235 				return;
   1236 			}
   1237 	} else if (len > 1 && p[0] == '/' && p[1] == '*') {
   1238 		F_SET(sp, SC_SCR_TOP);
   1239 		do {
   1240 			for (; len > 1; --len, ++p)
   1241 				if (p[0] == '*' && p[1] == '/') {
   1242 					sp->lno = lno;
   1243 					return;
   1244 				}
   1245 		} while (!db_get(sp, ++lno, 0, &p, &len));
   1246 	} else if (len > 1 && p[0] == '/' && p[1] == '/') {
   1247 		F_SET(sp, SC_SCR_TOP);
   1248 		while (!db_get(sp, ++lno, 0, &p, &len))
   1249 			if (len < 1 || p[0] != '/' || p[1] != '/') {
   1250 				sp->lno = lno;
   1251 				return;
   1252 			}
   1253 	}
   1254 }
   1255 
   1256 /*
   1257  * file_m1 --
   1258  * 	First modification check routine.  The :next, :prev, :rewind, :tag,
   1259  *	:tagpush, :tagpop, ^^ modifications check.
   1260  *
   1261  * PUBLIC: int file_m1 __P((SCR *, int, int));
   1262  */
   1263 int
   1264 file_m1(SCR *sp, int force, int flags)
   1265 {
   1266 	EXF *ep;
   1267 
   1268 	ep = sp->ep;
   1269 
   1270 	/* If no file loaded, return no modifications. */
   1271 	if (ep == NULL)
   1272 		return (0);
   1273 
   1274 	/*
   1275 	 * If the file has been modified, we'll want to write it back or
   1276 	 * fail.  If autowrite is set, we'll write it back automatically,
   1277 	 * unless force is also set.  Otherwise, we fail unless forced or
   1278 	 * there's another open screen on this file.
   1279 	 */
   1280 	if (F_ISSET(ep, F_MODIFIED)) {
   1281 		if (O_ISSET(sp, O_AUTOWRITE)) {
   1282 			if (!force && file_aw(sp, flags))
   1283 				return (1);
   1284 		} else if (ep->refcnt <= 1 && !force) {
   1285 			msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ?
   1286 "262|File modified since last complete write; write or use ! to override" :
   1287 "263|File modified since last complete write; write or use :edit! to override");
   1288 			return (1);
   1289 		}
   1290 	}
   1291 
   1292 	return (file_m3(sp, force));
   1293 }
   1294 
   1295 /*
   1296  * file_m2 --
   1297  * 	Second modification check routine.  The :edit, :quit, :recover
   1298  *	modifications check.
   1299  *
   1300  * PUBLIC: int file_m2 __P((SCR *, int));
   1301  */
   1302 int
   1303 file_m2(SCR *sp, int force)
   1304 {
   1305 	EXF *ep;
   1306 
   1307 	ep = sp->ep;
   1308 
   1309 	/* If no file loaded, return no modifications. */
   1310 	if (ep == NULL)
   1311 		return (0);
   1312 
   1313 	/*
   1314 	 * If the file has been modified, we'll want to fail, unless forced
   1315 	 * or there's another open screen on this file.
   1316 	 */
   1317 	if (F_ISSET(ep, F_MODIFIED) && ep->refcnt <= 1 && !force) {
   1318 		msgq(sp, M_ERR,
   1319 "264|File modified since last complete write; write or use ! to override");
   1320 		return (1);
   1321 	}
   1322 
   1323 	return (file_m3(sp, force));
   1324 }
   1325 
   1326 /*
   1327  * file_m3 --
   1328  * 	Third modification check routine.
   1329  *
   1330  * PUBLIC: int file_m3 __P((SCR *, int));
   1331  */
   1332 int
   1333 file_m3(SCR *sp, int force)
   1334 {
   1335 	EXF *ep;
   1336 
   1337 	ep = sp->ep;
   1338 
   1339 	/* If no file loaded, return no modifications. */
   1340 	if (ep == NULL)
   1341 		return (0);
   1342 
   1343 	/*
   1344 	 * Don't exit while in a temporary files if the file was ever modified.
   1345 	 * The problem is that if the user does a ":wq", we write and quit,
   1346 	 * unlinking the temporary file.  Not what the user had in mind at all.
   1347 	 * We permit writing to temporary files, so that user maps using file
   1348 	 * system names work with temporary files.
   1349 	 */
   1350 	if (F_ISSET(sp->frp, FR_TMPEXIT) && ep->refcnt <= 1 && !force) {
   1351 		msgq(sp, M_ERR,
   1352 		    "265|File is a temporary; exit will discard modifications");
   1353 		return (1);
   1354 	}
   1355 	return (0);
   1356 }
   1357 
   1358 /*
   1359  * file_aw --
   1360  *	Autowrite routine.  If modified, autowrite is set and the readonly bit
   1361  *	is not set, write the file.  A routine so there's a place to put the
   1362  *	comment.
   1363  *
   1364  * PUBLIC: int file_aw __P((SCR *, int));
   1365  */
   1366 int
   1367 file_aw(SCR *sp, int flags)
   1368 {
   1369 	if (!F_ISSET(sp->ep, F_MODIFIED))
   1370 		return (0);
   1371 	if (!O_ISSET(sp, O_AUTOWRITE))
   1372 		return (0);
   1373 
   1374 	/*
   1375 	 * !!!
   1376 	 * Historic 4BSD vi attempted to write the file if autowrite was set,
   1377 	 * regardless of the writeability of the file (as defined by the file
   1378 	 * readonly flag).  System V changed this as some point, not attempting
   1379 	 * autowrite if the file was readonly.  This feels like a bug fix to
   1380 	 * me (e.g. the principle of least surprise is violated if readonly is
   1381 	 * set and vi writes the file), so I'm compatible with System V.
   1382 	 */
   1383 	if (O_ISSET(sp, O_READONLY)) {
   1384 		msgq(sp, M_INFO,
   1385 		    "266|File readonly, modifications not auto-written");
   1386 		return (1);
   1387 	}
   1388 	return (file_write(sp, NULL, NULL, NULL, flags));
   1389 }
   1390 
   1391 /*
   1392  * set_alt_name --
   1393  *	Set the alternate pathname.
   1394  *
   1395  * Set the alternate pathname.  It's a routine because I wanted some place
   1396  * to hang this comment.  The alternate pathname (normally referenced using
   1397  * the special character '#' during file expansion and in the vi ^^ command)
   1398  * is set by almost all ex commands that take file names as arguments.  The
   1399  * rules go something like this:
   1400  *
   1401  *    1: If any ex command takes a file name as an argument (except for the
   1402  *	 :next command), the alternate pathname is set to that file name.
   1403  *	 This excludes the command ":e" and ":w !command" as no file name
   1404  *       was specified.  Note, historically, the :source command did not set
   1405  *	 the alternate pathname.  It does in nvi, for consistency.
   1406  *
   1407  *    2: However, if any ex command sets the current pathname, e.g. the
   1408  *	 ":e file" or ":rew" commands succeed, then the alternate pathname
   1409  *	 is set to the previous file's current pathname, if it had one.
   1410  *	 This includes the ":file" command and excludes the ":e" command.
   1411  *	 So, by rule #1 and rule #2, if ":edit foo" fails, the alternate
   1412  *	 pathname will be "foo", if it succeeds, the alternate pathname will
   1413  *	 be the previous current pathname.  The ":e" command will not set
   1414  *       the alternate or current pathnames regardless.
   1415  *
   1416  *    3: However, if it's a read or write command with a file argument and
   1417  *	 the current pathname has not yet been set, the file name becomes
   1418  *	 the current pathname, and the alternate pathname is unchanged.
   1419  *
   1420  * If the user edits a temporary file, there may be times when there is no
   1421  * alternative file name.  A name argument of NULL turns it off.
   1422  *
   1423  * PUBLIC: void set_alt_name __P((SCR *, const char *));
   1424  */
   1425 void
   1426 set_alt_name(SCR *sp, const char *name)
   1427 {
   1428 	if (sp->alt_name != NULL)
   1429 		free(sp->alt_name);
   1430 	if (name == NULL)
   1431 		sp->alt_name = NULL;
   1432 	else if ((sp->alt_name = strdup(name)) == NULL)
   1433 		msgq(sp, M_SYSERR, NULL);
   1434 }
   1435 
   1436 /*
   1437  * file_lock --
   1438  *	Get an exclusive lock on a file and set close-on-exec flag
   1439  *
   1440  * XXX
   1441  * The default locking is flock(2) style, not fcntl(2).  The latter is
   1442  * known to fail badly on some systems, and its only advantage is that
   1443  * it occasionally works over NFS.
   1444  *
   1445  * Furthermore, the semantics of fcntl(2) are wrong.  The problems are
   1446  * two-fold: you can't close any file descriptor associated with the file
   1447  * without losing all of the locks, and you can't get an exclusive lock
   1448  * unless you have the file open for writing.  Someone ought to be shot,
   1449  * but it's probably too late, they may already have reproduced.  To get
   1450  * around these problems, nvi opens the files for writing when it can and
   1451  * acquires a second file descriptor when it can't.  The recovery files
   1452  * are examples of the former, they're always opened for writing.  The DB
   1453  * files can't be opened for writing because the semantics of DB are that
   1454  * files opened for writing are flushed back to disk when the DB session
   1455  * is ended. So, in that case we have to acquire an extra file descriptor.
   1456  *
   1457  * PUBLIC: lockr_t file_lock __P((SCR *, char *, int *, int, int));
   1458  */
   1459 lockr_t
   1460 file_lock(SCR *sp, char *name, int *fdp, int fd, int iswrite)
   1461 {
   1462 	fcntl(fd, F_SETFD, 1);
   1463 
   1464 	if (!O_ISSET(sp, O_LOCKFILES))
   1465 		return (LOCK_SUCCESS);
   1466 
   1467 #ifdef HAVE_LOCK_FLOCK			/* Hurrah!  We've got flock(2). */
   1468 	/*
   1469 	 * !!!
   1470 	 * We need to distinguish a lock not being available for the file
   1471 	 * from the file system not supporting locking.  Flock is documented
   1472 	 * as returning EWOULDBLOCK; add EAGAIN for good measure, and assume
   1473 	 * they are the former.  There's no portable way to do this.
   1474 	 */
   1475 	errno = 0;
   1476 	return (flock(fd, LOCK_EX | LOCK_NB) ? errno == EAGAIN
   1477 #ifdef EWOULDBLOCK
   1478 	    || errno == EWOULDBLOCK
   1479 #endif
   1480 	    ? LOCK_UNAVAIL : LOCK_FAILED : LOCK_SUCCESS);
   1481 #endif
   1482 #ifdef HAVE_LOCK_FCNTL			/* Gag me.  We've got fcntl(2). */
   1483 {
   1484 	struct flock arg;
   1485 	int didopen, sverrno;
   1486 
   1487 	arg.l_type = F_WRLCK;
   1488 	arg.l_whence = 0;		/* SEEK_SET */
   1489 	arg.l_start = arg.l_len = 0;
   1490 	arg.l_pid = 0;
   1491 
   1492 	/*
   1493 	 * If the file descriptor isn't opened for writing, it must fail.
   1494 	 * If we fail because we can't get a read/write file descriptor,
   1495 	 * we return LOCK_SUCCESS, believing that the file is readonly
   1496 	 * and that will be sufficient to warn the user.
   1497 	 */
   1498 	if (!iswrite) {
   1499 		if (name == NULL || fdp == NULL)
   1500 			return (LOCK_FAILED);
   1501 		if ((fd = open(name, O_RDWR, 0)) == -1)
   1502 			return (LOCK_SUCCESS);
   1503 		*fdp = fd;
   1504 		didopen = 1;
   1505 	}
   1506 
   1507 	errno = 0;
   1508 	if (!fcntl(fd, F_SETLK, &arg))
   1509 		return (LOCK_SUCCESS);
   1510 	if (didopen) {
   1511 		sverrno = errno;
   1512 		(void)close(fd);
   1513 		errno = sverrno;
   1514 	}
   1515 
   1516 	/*
   1517 	 * !!!
   1518 	 * We need to distinguish a lock not being available for the file
   1519 	 * from the file system not supporting locking.  Fcntl is documented
   1520 	 * as returning EACCESS and EAGAIN; add EWOULDBLOCK for good measure,
   1521 	 * and assume they are the former.  There's no portable way to do this.
   1522 	 */
   1523 	return (errno == EACCES || errno == EAGAIN
   1524 #ifdef EWOULDBLOCK
   1525 	|| errno == EWOULDBLOCK
   1526 #endif
   1527 	?  LOCK_UNAVAIL : LOCK_FAILED);
   1528 }
   1529 #endif
   1530 #if !defined(HAVE_LOCK_FLOCK) && !defined(HAVE_LOCK_FCNTL)
   1531 	return (LOCK_SUCCESS);
   1532 #endif
   1533 }
   1534