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