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