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