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