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