1 /*- 2 * Copyright (c) 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1992, 1993, 1994, 1995, 1996 5 * Keith Bostic. All rights reserved. 6 * 7 * See the LICENSE file for redistribution information. 8 */ 9 10 #include "config.h" 11 12 #ifndef lint 13 static const char sccsid[] = "$Id: exf.c,v 10.62 2013/07/01 23:28:13 zy Exp $"; 14 #endif /* not lint */ 15 16 #include <sys/types.h> 17 #include <sys/queue.h> 18 #include <sys/stat.h> 19 #include <sys/time.h> 20 21 /* 22 * We include <sys/file.h>, because the flock(2) and open(2) #defines 23 * were found there on historical systems. We also include <fcntl.h> 24 * because the open(2) #defines are found there on newer systems. 25 */ 26 #include <sys/file.h> 27 28 #include <bitstring.h> 29 #include <dirent.h> 30 #include <errno.h> 31 #include <fcntl.h> 32 #include <limits.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <unistd.h> 37 38 #include "common.h" 39 40 static int file_backup __P((SCR *, char *, char *)); 41 static void file_cinit __P((SCR *)); 42 static void file_encinit __P((SCR *)); 43 static void file_comment __P((SCR *)); 44 static int file_spath __P((SCR *, FREF *, struct stat *, int *)); 45 46 /* 47 * file_add -- 48 * Insert a file name into the FREF list, if it doesn't already 49 * appear in it. 50 * 51 * !!! 52 * The "if it doesn't already appear" changes vi's semantics slightly. If 53 * you do a "vi foo bar", and then execute "next bar baz", the edit of bar 54 * will reflect the line/column of the previous edit session. Historic nvi 55 * did not do this. The change is a logical extension of the change where 56 * vi now remembers the last location in any file that it has ever edited, 57 * not just the previously edited file. 58 * 59 * PUBLIC: FREF *file_add __P((SCR *, char *)); 60 */ 61 FREF * 62 file_add( 63 SCR *sp, 64 char *name) 65 { 66 GS *gp; 67 FREF *frp, *tfrp; 68 69 /* 70 * Return it if it already exists. Note that we test against the 71 * user's name, whatever that happens to be, including if it's a 72 * temporary file. 73 * 74 * If the user added a file but was unable to initialize it, there 75 * can be file list entries where the name field is NULL. Discard 76 * them the next time we see them. 77 */ 78 gp = sp->gp; 79 if (name != NULL) 80 TAILQ_FOREACH_SAFE(frp, gp->frefq, q, tfrp) { 81 if (frp->name == NULL) { 82 TAILQ_REMOVE(gp->frefq, frp, q); 83 if (frp->name != NULL) 84 free(frp->name); 85 free(frp); 86 continue; 87 } 88 if (!strcmp(frp->name, name)) 89 return (frp); 90 } 91 92 /* Allocate and initialize the FREF structure. */ 93 CALLOC(sp, frp, FREF *, 1, sizeof(FREF)); 94 if (frp == NULL) 95 return (NULL); 96 97 /* 98 * If no file name specified, or if the file name is a request 99 * for something temporary, file_init() will allocate the file 100 * name. Temporary files are always ignored. 101 */ 102 if (name != NULL && strcmp(name, TEMPORARY_FILE_STRING) && 103 (frp->name = strdup(name)) == NULL) { 104 free(frp); 105 msgq(sp, M_SYSERR, NULL); 106 return (NULL); 107 } 108 109 /* Append into the chain of file names. */ 110 TAILQ_INSERT_TAIL(gp->frefq, frp, q); 111 112 return (frp); 113 } 114 115 /* 116 * file_init -- 117 * Start editing a file, based on the FREF structure. If successsful, 118 * let go of any previous file. Don't release the previous file until 119 * absolutely sure we have the new one. 120 * 121 * PUBLIC: int file_init __P((SCR *, FREF *, char *, int)); 122 */ 123 int 124 file_init( 125 SCR *sp, 126 FREF *frp, 127 char *rcv_name, 128 int flags) 129 { 130 EXF *ep; 131 RECNOINFO oinfo = { 0 }; 132 struct stat sb; 133 size_t psize; 134 int fd, exists, open_err, readonly; 135 char *oname, *tname; 136 137 open_err = readonly = 0; 138 139 /* 140 * If the file is a recovery file, let the recovery code handle it. 141 * Clear the FR_RECOVER flag first -- the recovery code does set up, 142 * and then calls us! If the recovery call fails, it's probably 143 * because the named file doesn't exist. So, move boldly forward, 144 * presuming that there's an error message the user will get to see. 145 */ 146 if (F_ISSET(frp, FR_RECOVER)) { 147 F_CLR(frp, FR_RECOVER); 148 return (rcv_read(sp, frp)); 149 } 150 151 /* 152 * Required FRP initialization; the only flag we keep is the 153 * cursor information. 154 */ 155 F_CLR(frp, ~FR_CURSORSET); 156 157 /* 158 * Required EXF initialization: 159 * Flush the line caches. 160 * Default recover mail file fd to -1. 161 * Set initial EXF flag bits. 162 */ 163 CALLOC_RET(sp, ep, EXF *, 1, sizeof(EXF)); 164 ep->c_lno = ep->c_nlines = OOBLNO; 165 ep->rcv_fd = -1; 166 F_SET(ep, F_FIRSTMODIFY); 167 168 /* 169 * Scan the user's path to find the file that we're going to 170 * try and open. 171 */ 172 if (file_spath(sp, frp, &sb, &exists)) 173 return (1); 174 175 /* 176 * If no name or backing file, for whatever reason, create a backing 177 * temporary file, saving the temp file name so we can later unlink 178 * it. If the user never named this file, copy the temporary file name 179 * to the real name (we display that until the user renames it). 180 */ 181 oname = frp->name; 182 if (LF_ISSET(FS_OPENERR) || oname == NULL || !exists) { 183 struct stat sb; 184 185 if (opts_empty(sp, O_TMPDIR, 0)) 186 goto err; 187 if ((tname = 188 join(O_STR(sp, O_TMPDIR), "vi.XXXXXXXXXX")) == NULL) { 189 msgq(sp, M_SYSERR, NULL); 190 goto err; 191 } 192 if ((fd = mkstemp(tname)) == -1 || fstat(fd, &sb)) { 193 free(tname); 194 msgq(sp, M_SYSERR, 195 "237|Unable to create temporary file"); 196 goto err; 197 } 198 (void)close(fd); 199 200 frp->tname = tname; 201 if (frp->name == NULL) { 202 F_SET(frp, FR_TMPFILE); 203 if ((frp->name = strdup(tname)) == NULL) { 204 msgq(sp, M_SYSERR, NULL); 205 goto err; 206 } 207 } 208 oname = frp->tname; 209 psize = 1024; 210 if (!LF_ISSET(FS_OPENERR)) 211 F_SET(frp, FR_NEWFILE); 212 213 ep->mtim = sb.st_mtimespec; 214 } else { 215 /* 216 * XXX 217 * A seat of the pants calculation: try to keep the file in 218 * 15 pages or less. Don't use a page size larger than 16K 219 * (vi should have good locality) or smaller than 1K. 220 */ 221 psize = ((sb.st_size / 15) + 1023) / 1024; 222 if (psize > 16) 223 psize = 16; 224 if (psize == 0) 225 psize = 1; 226 psize = p2roundup(psize) << 10; 227 228 F_SET(ep, F_DEVSET); 229 ep->mdev = sb.st_dev; 230 ep->minode = sb.st_ino; 231 232 ep->mtim = sb.st_mtimespec; 233 234 if (!S_ISREG(sb.st_mode)) 235 msgq_str(sp, M_ERR, oname, 236 "238|Warning: %s is not a regular file"); 237 } 238 239 /* Set up recovery. */ 240 oinfo.bval = '\n'; /* Always set. */ 241 oinfo.psize = psize; 242 oinfo.flags = F_ISSET(sp->gp, G_SNAPSHOT) ? R_SNAPSHOT : 0; 243 if (rcv_name == NULL) { 244 if (!rcv_tmp(sp, ep, frp->name)) 245 oinfo.bfname = ep->rcv_path; 246 } else { 247 if ((ep->rcv_path = strdup(rcv_name)) == NULL) { 248 msgq(sp, M_SYSERR, NULL); 249 goto err; 250 } 251 oinfo.bfname = ep->rcv_path; 252 F_SET(ep, F_MODIFIED); 253 } 254 255 /* Open a db structure. */ 256 if ((ep->db = dbopen(rcv_name == NULL ? oname : NULL, 257 O_NONBLOCK | O_RDONLY, 258 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, 259 DB_RECNO, &oinfo)) == NULL) { 260 msgq_str(sp, 261 M_SYSERR, rcv_name == NULL ? oname : rcv_name, "%s"); 262 /* 263 * !!! 264 * Historically, vi permitted users to edit files that couldn't 265 * be read. This isn't useful for single files from a command 266 * line, but it's quite useful for "vi *.c", since you can skip 267 * past files that you can't read. 268 */ 269 open_err = 1; 270 goto oerr; 271 } 272 273 /* 274 * Do the remaining things that can cause failure of the new file, 275 * mark and logging initialization. 276 */ 277 if (mark_init(sp, ep) || log_init(sp, ep)) 278 goto err; 279 280 /* 281 * Set the alternate file name to be the file we're discarding. 282 * 283 * !!! 284 * Temporary files can't become alternate files, so there's no file 285 * name. This matches historical practice, although it could only 286 * happen in historical vi as the result of the initial command, i.e. 287 * if vi was executed without a file name. 288 */ 289 if (LF_ISSET(FS_SETALT)) 290 set_alt_name(sp, sp->frp == NULL || 291 F_ISSET(sp->frp, FR_TMPFILE) ? NULL : sp->frp->name); 292 293 /* 294 * Close the previous file; if that fails, close the new one and run 295 * for the border. 296 * 297 * !!! 298 * There's a nasty special case. If the user edits a temporary file, 299 * and then does an ":e! %", we need to re-initialize the backing 300 * file, but we can't change the name. (It's worse -- we're dealing 301 * with *names* here, we can't even detect that it happened.) Set a 302 * flag so that the file_end routine ignores the backing information 303 * of the old file if it happens to be the same as the new one. 304 * 305 * !!! 306 * Side-effect: after the call to file_end(), sp->frp may be NULL. 307 */ 308 if (sp->ep != NULL) { 309 F_SET(frp, FR_DONTDELETE); 310 if (file_end(sp, NULL, LF_ISSET(FS_FORCE))) { 311 (void)file_end(sp, ep, 1); 312 goto err; 313 } 314 F_CLR(frp, FR_DONTDELETE); 315 } 316 317 /* 318 * Lock the file; if it's a recovery file, it should already be 319 * locked. Note, we acquire the lock after the previous file 320 * has been ended, so that we don't get an "already locked" error 321 * for ":edit!". 322 * 323 * XXX 324 * While the user can't interrupt us between the open and here, 325 * there's a race between the dbopen() and the lock. Not much 326 * we can do about it. 327 * 328 * XXX 329 * We don't make a big deal of not being able to lock the file. As 330 * locking rarely works over NFS, and often fails if the file was 331 * mmap(2)'d, it's far too common to do anything like print an error 332 * message, let alone make the file readonly. At some future time, 333 * when locking is a little more reliable, this should change to be 334 * an error. 335 */ 336 if (rcv_name == NULL) 337 switch (file_lock(sp, oname, 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 /* Detect and set the file encoding */ 407 file_encinit(sp); 408 409 /* Set the initial cursor position, queue initial command. */ 410 file_cinit(sp); 411 412 /* Redraw the screen from scratch, schedule a welcome message. */ 413 F_SET(sp, SC_SCR_REFORMAT | SC_STATUS); 414 415 return (0); 416 417 err: if (frp->name != NULL) { 418 free(frp->name); 419 frp->name = NULL; 420 } 421 if (frp->tname != NULL) { 422 (void)unlink(frp->tname); 423 free(frp->tname); 424 frp->tname = NULL; 425 } 426 427 oerr: if (F_ISSET(ep, F_RCV_ON)) 428 (void)unlink(ep->rcv_path); 429 if (ep->rcv_path != NULL) { 430 free(ep->rcv_path); 431 ep->rcv_path = NULL; 432 } 433 if (ep->db != NULL) 434 (void)ep->db->close(ep->db); 435 free(ep); 436 437 return (open_err ? 438 file_init(sp, frp, rcv_name, flags | FS_OPENERR) : 1); 439 } 440 441 /* 442 * file_spath -- 443 * Scan the user's path to find the file that we're going to 444 * try and open. 445 */ 446 static int 447 file_spath( 448 SCR *sp, 449 FREF *frp, 450 struct stat *sbp, 451 int *existsp) 452 { 453 int savech; 454 size_t len; 455 int found; 456 char *name, *p, *t, *path; 457 458 /* 459 * If the name is NULL or an explicit reference (i.e., the first 460 * component is . or ..) ignore the O_PATH option. 461 */ 462 name = frp->name; 463 if (name == NULL) { 464 *existsp = 0; 465 return (0); 466 } 467 if (name[0] == '/' || (name[0] == '.' && 468 (name[1] == '/' || (name[1] == '.' && name[2] == '/')))) { 469 *existsp = !stat(name, sbp); 470 return (0); 471 } 472 473 /* Try . */ 474 if (!stat(name, sbp)) { 475 *existsp = 1; 476 return (0); 477 } 478 479 /* Try the O_PATH option values. */ 480 for (found = 0, p = t = O_STR(sp, O_PATH);; ++p) 481 if (*p == ':' || *p == '\0') { 482 /* 483 * Ignore the empty strings and ".", since we've already 484 * tried the current directory. 485 */ 486 if (t < p && (p - t != 1 || *t != '.')) { 487 savech = *p; 488 *p = '\0'; 489 if ((path = join(t, name)) == NULL) { 490 msgq(sp, M_SYSERR, NULL); 491 break; 492 } 493 len = strlen(path); 494 *p = savech; 495 if (!stat(path, sbp)) { 496 found = 1; 497 break; 498 } 499 free(path); 500 } 501 t = p + 1; 502 if (*p == '\0') 503 break; 504 } 505 506 /* If we found it, build a new pathname and discard the old one. */ 507 if (found) { 508 free(frp->name); 509 frp->name = path; 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 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( 632 SCR *sp, 633 EXF *ep, 634 int force) 635 { 636 FREF *frp; 637 638 /* 639 * !!! 640 * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER. 641 * (If argument ep is NULL, use sp->ep.) 642 * 643 * If multiply referenced, just decrement the count and return. 644 */ 645 if (ep == NULL) 646 ep = sp->ep; 647 if (--ep->refcnt != 0) 648 return (0); 649 650 /* 651 * 652 * Clean up the FREF structure. 653 * 654 * Save the cursor location. 655 * 656 * XXX 657 * It would be cleaner to do this somewhere else, but by the time 658 * ex or vi knows that we're changing files it's already happened. 659 */ 660 frp = sp->frp; 661 frp->lno = sp->lno; 662 frp->cno = sp->cno; 663 F_SET(frp, FR_CURSORSET); 664 665 /* 666 * We may no longer need the temporary backing file, so clean it 667 * up. We don't need the FREF structure either, if the file was 668 * never named, so lose it. 669 * 670 * !!! 671 * Re: FR_DONTDELETE, see the comment above in file_init(). 672 */ 673 if (!F_ISSET(frp, FR_DONTDELETE) && frp->tname != NULL) { 674 if (unlink(frp->tname)) 675 msgq_str(sp, M_SYSERR, frp->tname, "240|%s: remove"); 676 free(frp->tname); 677 frp->tname = NULL; 678 if (F_ISSET(frp, FR_TMPFILE)) { 679 TAILQ_REMOVE(sp->gp->frefq, frp, q); 680 if (frp->name != NULL) 681 free(frp->name); 682 free(frp); 683 } 684 sp->frp = NULL; 685 } 686 687 /* 688 * Clean up the EXF structure. 689 * 690 * Close the db structure. 691 */ 692 if (ep->db->close != NULL && ep->db->close(ep->db) && !force) { 693 msgq_str(sp, M_SYSERR, frp->name, "241|%s: close"); 694 ++ep->refcnt; 695 return (1); 696 } 697 698 /* COMMITTED TO THE CLOSE. THERE'S NO GOING BACK... */ 699 700 /* Stop logging. */ 701 (void)log_end(sp, ep); 702 703 /* Free up any marks. */ 704 (void)mark_end(sp, ep); 705 706 /* 707 * Delete recovery files, close the open descriptor, free recovery 708 * memory. See recover.c for a description of the protocol. 709 * 710 * XXX 711 * Unlink backup file first, we can detect that the recovery file 712 * doesn't reference anything when the user tries to recover it. 713 * There's a race, here, obviously, but it's fairly small. 714 */ 715 if (!F_ISSET(ep, F_RCV_NORM)) { 716 if (ep->rcv_path != NULL && unlink(ep->rcv_path)) 717 msgq_str(sp, M_SYSERR, ep->rcv_path, "242|%s: remove"); 718 if (ep->rcv_mpath != NULL && unlink(ep->rcv_mpath)) 719 msgq_str(sp, M_SYSERR, ep->rcv_mpath, "243|%s: remove"); 720 } 721 if (ep->rcv_fd != -1) 722 (void)close(ep->rcv_fd); 723 if (ep->rcv_path != NULL) 724 free(ep->rcv_path); 725 if (ep->rcv_mpath != NULL) 726 free(ep->rcv_mpath); 727 if (ep->c_blen > 0) 728 free(ep->c_lp); 729 730 free(ep); 731 return (0); 732 } 733 734 /* 735 * file_write -- 736 * Write the file to disk. Historic vi had fairly convoluted 737 * semantics for whether or not writes would happen. That's 738 * why all the flags. 739 * 740 * PUBLIC: int file_write __P((SCR *, MARK *, MARK *, char *, int)); 741 */ 742 int 743 file_write( 744 SCR *sp, 745 MARK *fm, 746 MARK *tm, 747 char *name, 748 int flags) 749 { 750 enum { NEWFILE, OLDFILE } mtype; 751 struct stat sb; 752 EXF *ep; 753 FILE *fp; 754 FREF *frp; 755 MARK from, to; 756 size_t len; 757 u_long nlno, nch; 758 int fd, nf, noname, oflags, rval; 759 char *p, *s, *t, buf[1024]; 760 const char *msgstr; 761 762 ep = sp->ep; 763 frp = sp->frp; 764 765 /* 766 * Writing '%', or naming the current file explicitly, has the 767 * same semantics as writing without a name. 768 */ 769 if (name == NULL || !strcmp(name, frp->name)) { 770 noname = 1; 771 name = frp->name; 772 } else 773 noname = 0; 774 775 /* Can't write files marked read-only, unless forced. */ 776 if (!LF_ISSET(FS_FORCE) && noname && O_ISSET(sp, O_READONLY)) { 777 msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ? 778 "244|Read-only file, not written; use ! to override" : 779 "245|Read-only file, not written"); 780 return (1); 781 } 782 783 /* If not forced, not appending, and "writeany" not set ... */ 784 if (!LF_ISSET(FS_FORCE | FS_APPEND) && !O_ISSET(sp, O_WRITEANY)) { 785 /* Don't overwrite anything but the original file. */ 786 if ((!noname || F_ISSET(frp, FR_NAMECHANGE)) && 787 !stat(name, &sb)) { 788 msgq_str(sp, M_ERR, name, 789 LF_ISSET(FS_POSSIBLE) ? 790 "246|%s exists, not written; use ! to override" : 791 "247|%s exists, not written"); 792 return (1); 793 } 794 795 /* 796 * Don't write part of any existing file. Only test for the 797 * original file, the previous test catches anything else. 798 */ 799 if (!LF_ISSET(FS_ALL) && noname && !stat(name, &sb)) { 800 msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ? 801 "248|Partial file, not written; use ! to override" : 802 "249|Partial file, not written"); 803 return (1); 804 } 805 } 806 807 /* 808 * Figure out if the file already exists -- if it doesn't, we display 809 * the "new file" message. The stat might not be necessary, but we 810 * just repeat it because it's easier than hacking the previous tests. 811 * The information is only used for the user message and modification 812 * time test, so we can ignore the obvious race condition. 813 * 814 * One final test. If we're not forcing or appending the current file, 815 * and we have a saved modification time, object if the file changed 816 * since we last edited or wrote it, and make them force it. 817 */ 818 if (stat(name, &sb)) 819 mtype = NEWFILE; 820 else { 821 if (noname && !LF_ISSET(FS_FORCE | FS_APPEND) && 822 ((F_ISSET(ep, F_DEVSET) && 823 (sb.st_dev != ep->mdev || sb.st_ino != ep->minode)) || 824 timespeccmp(&sb.st_mtimespec, &ep->mtim, !=))) { 825 msgq_str(sp, M_ERR, name, LF_ISSET(FS_POSSIBLE) ? 826 "250|%s: file modified more recently than this copy; use ! to override" : 827 "251|%s: file modified more recently than this copy"); 828 return (1); 829 } 830 831 mtype = OLDFILE; 832 } 833 834 /* Set flags to create, write, and either append or truncate. */ 835 oflags = O_CREAT | O_WRONLY | 836 (LF_ISSET(FS_APPEND) ? O_APPEND : O_TRUNC); 837 838 /* Backup the file if requested. */ 839 if (!opts_empty(sp, O_BACKUP, 1) && 840 file_backup(sp, name, O_STR(sp, O_BACKUP)) && !LF_ISSET(FS_FORCE)) 841 return (1); 842 843 /* Open the file. */ 844 SIGBLOCK; 845 if ((fd = open(name, oflags, 846 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) < 0) { 847 if (errno == EACCES && LF_ISSET(FS_FORCE)) { 848 /* 849 * If the user owns the file but does not 850 * have write permission on it, grant it 851 * automatically for the duration of the 852 * opening of the file, if possible. 853 */ 854 struct stat sb; 855 mode_t fmode; 856 857 if (stat(name, &sb) != 0) 858 goto fail_open; 859 fmode = sb.st_mode; 860 if (!(sb.st_mode & S_IWUSR) && sb.st_uid == getuid()) 861 fmode |= S_IWUSR; 862 else 863 goto fail_open; 864 if (chmod(name, fmode) != 0) 865 goto fail_open; 866 fd = open(name, oflags, S_IRUSR | S_IWUSR | 867 S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 868 if (fd == -1) 869 goto fail_open; 870 (void)fchmod(fd, sb.st_mode); 871 goto success_open; 872 fail_open: 873 errno = EACCES; 874 } 875 msgq_str(sp, M_SYSERR, name, "%s"); 876 SIGUNBLOCK; 877 return (1); 878 } 879 success_open: 880 SIGUNBLOCK; 881 882 /* Try and get a lock. */ 883 if (!noname && file_lock(sp, NULL, fd, 0) == LOCK_UNAVAIL) 884 msgq_str(sp, M_ERR, name, 885 "252|%s: write lock was unavailable"); 886 887 /* 888 * Use stdio for buffering. 889 * 890 * XXX 891 * SVR4.2 requires the fdopen mode exactly match the original open 892 * mode, i.e. you have to open with "a" if appending. 893 */ 894 if ((fp = fdopen(fd, LF_ISSET(FS_APPEND) ? "a" : "w")) == NULL) { 895 msgq_str(sp, M_SYSERR, name, "%s"); 896 (void)close(fd); 897 return (1); 898 } 899 900 /* Build fake addresses, if necessary. */ 901 if (fm == NULL) { 902 from.lno = 1; 903 from.cno = 0; 904 fm = &from; 905 if (db_last(sp, &to.lno)) 906 return (1); 907 to.cno = 0; 908 tm = &to; 909 } 910 911 rval = ex_writefp(sp, name, fp, fm, tm, &nlno, &nch, 0); 912 913 /* 914 * Save the new last modification time -- even if the write fails 915 * we re-init the time. That way the user can clean up the disk 916 * and rewrite without having to force it. 917 */ 918 if (noname) 919 if (stat(name, &sb)) 920 timepoint_system(&ep->mtim); 921 else { 922 F_SET(ep, F_DEVSET); 923 ep->mdev = sb.st_dev; 924 ep->minode = sb.st_ino; 925 926 ep->mtim = sb.st_mtimespec; 927 } 928 929 /* 930 * If the write failed, complain loudly. ex_writefp() has already 931 * complained about the actual error, reinforce it if data was lost. 932 */ 933 if (rval) { 934 if (!LF_ISSET(FS_APPEND)) 935 msgq_str(sp, M_ERR, name, 936 "254|%s: WARNING: FILE TRUNCATED"); 937 return (1); 938 } 939 940 /* 941 * Once we've actually written the file, it doesn't matter that the 942 * file name was changed -- if it was, we've already whacked it. 943 */ 944 F_CLR(frp, FR_NAMECHANGE); 945 946 /* 947 * If wrote the entire file, and it wasn't by appending it to a file, 948 * clear the modified bit. If the file was written to the original 949 * file name and the file is a temporary, set the "no exit" bit. This 950 * permits the user to write the file and use it in the context of the 951 * filesystem, but still keeps them from discarding their changes by 952 * exiting. 953 */ 954 if (LF_ISSET(FS_ALL) && !LF_ISSET(FS_APPEND)) { 955 F_CLR(ep, F_MODIFIED); 956 if (F_ISSET(frp, FR_TMPFILE)) 957 if (noname) 958 F_SET(frp, FR_TMPEXIT); 959 else 960 F_CLR(frp, FR_TMPEXIT); 961 } 962 963 p = msg_print(sp, name, &nf); 964 switch (mtype) { 965 case NEWFILE: 966 msgstr = msg_cat(sp, 967 "256|%s: new file: %lu lines, %lu characters", NULL); 968 len = snprintf(buf, sizeof(buf), msgstr, p, nlno, nch); 969 break; 970 case OLDFILE: 971 msgstr = msg_cat(sp, LF_ISSET(FS_APPEND) ? 972 "315|%s: appended: %lu lines, %lu characters" : 973 "257|%s: %lu lines, %lu characters", NULL); 974 len = snprintf(buf, sizeof(buf), msgstr, p, nlno, nch); 975 break; 976 default: 977 abort(); 978 } 979 980 /* 981 * There's a nasty problem with long path names. Cscope and tags files 982 * can result in long paths and vi will request a continuation key from 983 * the user. Unfortunately, the user has typed ahead, and chaos will 984 * result. If we assume that the characters in the filenames only take 985 * a single screen column each, we can trim the filename. 986 */ 987 s = buf; 988 if (len >= sp->cols) { 989 for (s = buf, t = buf + strlen(p); s < t && 990 (*s != '/' || len >= sp->cols - 3); ++s, --len); 991 if (s == t) 992 s = buf; 993 else { 994 *--s = '.'; /* Leading ellipses. */ 995 *--s = '.'; 996 *--s = '.'; 997 } 998 } 999 msgq(sp, M_INFO, "%s", s); 1000 if (nf) 1001 FREE_SPACE(sp, p, 0); 1002 return (0); 1003 } 1004 1005 /* 1006 * file_backup -- 1007 * Backup the about-to-be-written file. 1008 * 1009 * XXX 1010 * We do the backup by copying the entire file. It would be nice to do 1011 * a rename instead, but: (1) both files may not fit and we want to fail 1012 * before doing the rename; (2) the backup file may not be on the same 1013 * disk partition as the file being written; (3) there may be optional 1014 * file information (MACs, DACs, whatever) that we won't get right if we 1015 * recreate the file. So, let's not risk it. 1016 */ 1017 static int 1018 file_backup( 1019 SCR *sp, 1020 char *name, 1021 char *bname) 1022 { 1023 struct dirent *dp; 1024 struct stat sb; 1025 DIR *dirp; 1026 EXCMD cmd; 1027 off_t off; 1028 size_t blen; 1029 int flags, maxnum, nr, num, nw, rfd, wfd, version; 1030 char *bp, *estr, *p, *pct, *slash, *t, *wfname, buf[8192]; 1031 CHAR_T *wp; 1032 size_t wlen; 1033 size_t nlen; 1034 char *d = NULL; 1035 1036 rfd = wfd = -1; 1037 bp = estr = wfname = NULL; 1038 1039 /* 1040 * Open the current file for reading. Do this first, so that 1041 * we don't exec a shell before the most likely failure point. 1042 * If it doesn't exist, it's okay, there's just nothing to back 1043 * up. 1044 */ 1045 errno = 0; 1046 if ((rfd = open(name, O_RDONLY, 0)) < 0) { 1047 if (errno == ENOENT) 1048 return (0); 1049 estr = name; 1050 goto err; 1051 } 1052 1053 /* 1054 * If the name starts with an 'N' character, add a version number 1055 * to the name. Strip the leading N from the string passed to the 1056 * expansion routines, for no particular reason. It would be nice 1057 * to permit users to put the version number anywhere in the backup 1058 * name, but there isn't a special character that we can use in the 1059 * name, and giving a new character a special meaning leads to ugly 1060 * hacks both here and in the supporting ex routines. 1061 * 1062 * Shell and file name expand the option's value. 1063 */ 1064 ex_cinit(sp, &cmd, 0, 0, 0, 0, 0); 1065 if (bname[0] == 'N') { 1066 version = 1; 1067 ++bname; 1068 } else 1069 version = 0; 1070 CHAR2INT(sp, bname, strlen(bname), wp, wlen); 1071 if ((wp = v_wstrdup(sp, wp, wlen)) == NULL) 1072 return (1); 1073 if (argv_exp2(sp, &cmd, wp, wlen)) { 1074 free(wp); 1075 return (1); 1076 } 1077 free(wp); 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 INT2CHAR(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 INT2CHAR(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 INT2CHAR(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 return (0); 1193 1194 alloc_err: 1195 err: if (rfd != -1) 1196 (void)close(rfd); 1197 if (wfd != -1) { 1198 (void)unlink(wfname); 1199 (void)close(wfd); 1200 } 1201 if (estr) 1202 msgq_str(sp, M_SYSERR, estr, "%s"); 1203 if (d != NULL) 1204 free(d); 1205 if (bp != NULL) 1206 FREE_SPACE(sp, bp, blen); 1207 return (1); 1208 } 1209 1210 /* 1211 * file_encinit -- 1212 * Read the first line and set the O_FILEENCODING. 1213 */ 1214 static void 1215 file_encinit(SCR *sp) 1216 { 1217 #if defined(USE_WIDECHAR) && defined(USE_ICONV) 1218 size_t len; 1219 char *p; 1220 size_t blen = 0; 1221 char buf[4096]; /* not need to be '\0'-terminated */ 1222 recno_t ln = 1; 1223 EXF *ep; 1224 1225 ep = sp->ep; 1226 1227 while (!db_rget(sp, ln++, &p, &len)) { 1228 if (blen + len > sizeof(buf)) 1229 len = sizeof(buf) - blen; 1230 memcpy(buf + blen, p, len); 1231 blen += len; 1232 if (blen == sizeof(buf)) 1233 break; 1234 else 1235 buf[blen++] = '\n'; 1236 } 1237 1238 /* 1239 * Detect UTF-8 and fallback to the locale/preset encoding. 1240 * 1241 * XXX 1242 * A manually set O_FILEENCODING indicates the "fallback 1243 * encoding", but UTF-8, which can be safely detected, is not 1244 * inherited from the old screen. 1245 */ 1246 if (looks_utf8(buf, blen) > 1) 1247 o_set(sp, O_FILEENCODING, OS_STRDUP, "utf-8", 0); 1248 else if (!O_ISSET(sp, O_FILEENCODING) || 1249 !strncasecmp(O_STR(sp, O_FILEENCODING), "utf-8", 5)) 1250 o_set(sp, O_FILEENCODING, OS_STRDUP, codeset(), 0); 1251 1252 conv_enc(sp, O_FILEENCODING, 0); 1253 #endif 1254 } 1255 1256 /* 1257 * file_comment -- 1258 * Skip the first comment. 1259 */ 1260 static void 1261 file_comment(SCR *sp) 1262 { 1263 recno_t lno; 1264 size_t len; 1265 CHAR_T *p; 1266 1267 for (lno = 1; !db_get(sp, lno, 0, &p, &len) && len == 0; ++lno); 1268 if (p == NULL) 1269 return; 1270 if (p[0] == '#') { 1271 F_SET(sp, SC_SCR_TOP); 1272 while (!db_get(sp, ++lno, 0, &p, &len)) 1273 if (len < 1 || p[0] != '#') { 1274 sp->lno = lno; 1275 return; 1276 } 1277 } else if (len > 1 && p[0] == '/' && p[1] == '*') { 1278 F_SET(sp, SC_SCR_TOP); 1279 do { 1280 for (; len > 1; --len, ++p) 1281 if (p[0] == '*' && p[1] == '/') { 1282 sp->lno = lno; 1283 return; 1284 } 1285 } while (!db_get(sp, ++lno, 0, &p, &len)); 1286 } else if (len > 1 && p[0] == '/' && p[1] == '/') { 1287 F_SET(sp, SC_SCR_TOP); 1288 p += 2; 1289 len -= 2; 1290 do { 1291 for (; len > 1; --len, ++p) 1292 if (p[0] == '/' && p[1] == '/') { 1293 sp->lno = lno; 1294 return; 1295 } 1296 } while (!db_get(sp, ++lno, 0, &p, &len)); 1297 } 1298 } 1299 1300 /* 1301 * file_m1 -- 1302 * First modification check routine. The :next, :prev, :rewind, :tag, 1303 * :tagpush, :tagpop, ^^ modifications check. 1304 * 1305 * PUBLIC: int file_m1 __P((SCR *, int, int)); 1306 */ 1307 int 1308 file_m1( 1309 SCR *sp, 1310 int force, 1311 int flags) 1312 { 1313 EXF *ep; 1314 1315 ep = sp->ep; 1316 1317 /* If no file loaded, return no modifications. */ 1318 if (ep == NULL) 1319 return (0); 1320 1321 /* 1322 * If the file has been modified, we'll want to write it back or 1323 * fail. If autowrite is set, we'll write it back automatically, 1324 * unless force is also set. Otherwise, we fail unless forced or 1325 * there's another open screen on this file. 1326 */ 1327 if (F_ISSET(ep, F_MODIFIED)) 1328 if (O_ISSET(sp, O_AUTOWRITE)) { 1329 if (!force && file_aw(sp, flags)) 1330 return (1); 1331 } else if (ep->refcnt <= 1 && !force) { 1332 msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ? 1333 "262|File modified since last complete write; write or use ! to override" : 1334 "263|File modified since last complete write; write or use :edit! to override"); 1335 return (1); 1336 } 1337 1338 return (file_m3(sp, force)); 1339 } 1340 1341 /* 1342 * file_m2 -- 1343 * Second modification check routine. The :edit, :quit, :recover 1344 * modifications check. 1345 * 1346 * PUBLIC: int file_m2 __P((SCR *, int)); 1347 */ 1348 int 1349 file_m2( 1350 SCR *sp, 1351 int force) 1352 { 1353 EXF *ep; 1354 1355 ep = sp->ep; 1356 1357 /* If no file loaded, return no modifications. */ 1358 if (ep == NULL) 1359 return (0); 1360 1361 /* 1362 * If the file has been modified, we'll want to fail, unless forced 1363 * or there's another open screen on this file. 1364 */ 1365 if (F_ISSET(ep, F_MODIFIED) && ep->refcnt <= 1 && !force) { 1366 msgq(sp, M_ERR, 1367 "264|File modified since last complete write; write or use ! to override"); 1368 return (1); 1369 } 1370 1371 return (file_m3(sp, force)); 1372 } 1373 1374 /* 1375 * file_m3 -- 1376 * Third modification check routine. 1377 * 1378 * PUBLIC: int file_m3 __P((SCR *, int)); 1379 */ 1380 int 1381 file_m3( 1382 SCR *sp, 1383 int force) 1384 { 1385 EXF *ep; 1386 1387 ep = sp->ep; 1388 1389 /* If no file loaded, return no modifications. */ 1390 if (ep == NULL) 1391 return (0); 1392 1393 /* 1394 * Don't exit while in a temporary files if the file was ever modified. 1395 * The problem is that if the user does a ":wq", we write and quit, 1396 * unlinking the temporary file. Not what the user had in mind at all. 1397 * We permit writing to temporary files, so that user maps using file 1398 * system names work with temporary files. 1399 */ 1400 if (F_ISSET(sp->frp, FR_TMPEXIT) && ep->refcnt <= 1 && !force) { 1401 msgq(sp, M_ERR, 1402 "265|File is a temporary; exit will discard modifications"); 1403 return (1); 1404 } 1405 return (0); 1406 } 1407 1408 /* 1409 * file_aw -- 1410 * Autowrite routine. If modified, autowrite is set and the readonly bit 1411 * is not set, write the file. A routine so there's a place to put the 1412 * comment. 1413 * 1414 * PUBLIC: int file_aw __P((SCR *, int)); 1415 */ 1416 int 1417 file_aw( 1418 SCR *sp, 1419 int flags) 1420 { 1421 if (!F_ISSET(sp->ep, F_MODIFIED)) 1422 return (0); 1423 if (!O_ISSET(sp, O_AUTOWRITE)) 1424 return (0); 1425 1426 /* 1427 * !!! 1428 * Historic 4BSD vi attempted to write the file if autowrite was set, 1429 * regardless of the writeability of the file (as defined by the file 1430 * readonly flag). System V changed this as some point, not attempting 1431 * autowrite if the file was readonly. This feels like a bug fix to 1432 * me (e.g. the principle of least surprise is violated if readonly is 1433 * set and vi writes the file), so I'm compatible with System V. 1434 */ 1435 if (O_ISSET(sp, O_READONLY)) { 1436 msgq(sp, M_INFO, 1437 "266|File readonly, modifications not auto-written"); 1438 return (1); 1439 } 1440 return (file_write(sp, NULL, NULL, NULL, flags)); 1441 } 1442 1443 /* 1444 * set_alt_name -- 1445 * Set the alternate pathname. 1446 * 1447 * Set the alternate pathname. It's a routine because I wanted some place 1448 * to hang this comment. The alternate pathname (normally referenced using 1449 * the special character '#' during file expansion and in the vi ^^ command) 1450 * is set by almost all ex commands that take file names as arguments. The 1451 * rules go something like this: 1452 * 1453 * 1: If any ex command takes a file name as an argument (except for the 1454 * :next command), the alternate pathname is set to that file name. 1455 * This excludes the command ":e" and ":w !command" as no file name 1456 * was specified. Note, historically, the :source command did not set 1457 * the alternate pathname. It does in nvi, for consistency. 1458 * 1459 * 2: However, if any ex command sets the current pathname, e.g. the 1460 * ":e file" or ":rew" commands succeed, then the alternate pathname 1461 * is set to the previous file's current pathname, if it had one. 1462 * This includes the ":file" command and excludes the ":e" command. 1463 * So, by rule #1 and rule #2, if ":edit foo" fails, the alternate 1464 * pathname will be "foo", if it succeeds, the alternate pathname will 1465 * be the previous current pathname. The ":e" command will not set 1466 * the alternate or current pathnames regardless. 1467 * 1468 * 3: However, if it's a read or write command with a file argument and 1469 * the current pathname has not yet been set, the file name becomes 1470 * the current pathname, and the alternate pathname is unchanged. 1471 * 1472 * If the user edits a temporary file, there may be times when there is no 1473 * alternative file name. A name argument of NULL turns it off. 1474 * 1475 * PUBLIC: void set_alt_name __P((SCR *, char *)); 1476 */ 1477 void 1478 set_alt_name( 1479 SCR *sp, 1480 char *name) 1481 { 1482 if (sp->alt_name != NULL) 1483 free(sp->alt_name); 1484 if (name == NULL) 1485 sp->alt_name = NULL; 1486 else if ((sp->alt_name = strdup(name)) == NULL) 1487 msgq(sp, M_SYSERR, NULL); 1488 } 1489 1490 /* 1491 * file_lock -- 1492 * Get an exclusive lock on a file. 1493 * 1494 * PUBLIC: lockr_t file_lock __P((SCR *, char *, int, int)); 1495 */ 1496 lockr_t 1497 file_lock( 1498 SCR *sp, 1499 char *name, 1500 int fd, 1501 int iswrite) 1502 { 1503 if (!O_ISSET(sp, O_LOCKFILES)) 1504 return (LOCK_SUCCESS); 1505 1506 /* 1507 * !!! 1508 * We need to distinguish a lock not being available for the file 1509 * from the file system not supporting locking. Flock is documented 1510 * as returning EWOULDBLOCK; add EAGAIN for good measure, and assume 1511 * they are the former. There's no portable way to do this. 1512 */ 1513 errno = 0; 1514 if (!flock(fd, LOCK_EX | LOCK_NB)) { 1515 fcntl(fd, F_SETFD, 1); 1516 return (LOCK_SUCCESS); 1517 } 1518 return (errno == EAGAIN 1519 #ifdef EWOULDBLOCK 1520 || errno == EWOULDBLOCK 1521 #endif 1522 ? LOCK_UNAVAIL : LOCK_FAILED); 1523 } 1524