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