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