edit.c revision 60786
1351278Sdim/* 2351278Sdim * Copyright (C) 1984-2000 Mark Nudelman 3351278Sdim * 4351278Sdim * You may distribute under the terms of either the GNU General Public 5351278Sdim * License or the Less License, as specified in the README file. 6351278Sdim * 7351278Sdim * For more information about less, or for information on how to 8351278Sdim * contact the author, see the README file. 9351278Sdim */ 10351278Sdim 11351278Sdim 12351278Sdim#include "less.h" 13351278Sdim 14351278Sdimpublic int fd0 = 0; 15351278Sdim 16351278Sdimextern int new_file; 17351278Sdimextern int errmsgs; 18351278Sdimextern int cbufs; 19351278Sdimextern char *every_first_cmd; 20351278Sdimextern int any_display; 21351278Sdimextern int force_open; 22351278Sdimextern int is_tty; 23351278Sdimextern int sigs; 24351278Sdimextern IFILE curr_ifile; 25360784Sdimextern IFILE old_ifile; 26351278Sdimextern struct scrpos initial_scrpos; 27351278Sdimextern void constant *ml_examine; 28351278Sdim#if SPACES_IN_FILENAMES 29351278Sdimextern char openquote; 30351278Sdimextern char closequote; 31351278Sdim#endif 32351278Sdim 33351278Sdim#if LOGFILE 34351278Sdimextern int logfile; 35351278Sdimextern int force_logfile; 36351278Sdimextern char *namelogfile; 37351278Sdim#endif 38351278Sdim 39351278Sdimchar *curr_altfilename = NULL; 40351278Sdimstatic void *curr_altpipe; 41351278Sdim 42351278Sdim 43351278Sdim/* 44351278Sdim * Textlist functions deal with a list of words separated by spaces. 45351278Sdim * init_textlist sets up a textlist structure. 46351278Sdim * forw_textlist uses that structure to iterate thru the list of 47351278Sdim * words, returning each one as a standard null-terminated string. 48351278Sdim * back_textlist does the same, but runs thru the list backwards. 49351278Sdim */ 50351278Sdim public void 51351278Sdiminit_textlist(tlist, str) 52351278Sdim struct textlist *tlist; 53351278Sdim char *str; 54351278Sdim{ 55351278Sdim char *s; 56351278Sdim#if SPACES_IN_FILENAMES 57351278Sdim int quoted = 0; 58351278Sdim#endif 59351278Sdim 60351278Sdim tlist->string = skipsp(str); 61351278Sdim tlist->endstring = tlist->string + strlen(tlist->string); 62351278Sdim for (s = str; s < tlist->endstring; s++) 63351278Sdim { 64351278Sdim#if SPACES_IN_FILENAMES 65351278Sdim if (*s == ' ' && !quoted) 66351278Sdim *s = '\0'; 67351278Sdim if (!quoted && *s == openquote) 68351278Sdim quoted = 1; 69351278Sdim else if (quoted && *s == closequote) 70351278Sdim quoted = 0; 71351278Sdim#else 72351278Sdim if (*s == ' ') 73351278Sdim *s = '\0'; 74351278Sdim#endif 75351278Sdim } 76351278Sdim} 77351278Sdim 78351278Sdim public char * 79351278Sdimforw_textlist(tlist, prev) 80351278Sdim struct textlist *tlist; 81351278Sdim char *prev; 82351278Sdim{ 83351278Sdim char *s; 84351278Sdim 85351278Sdim /* 86351278Sdim * prev == NULL means return the first word in the list. 87351278Sdim * Otherwise, return the word after "prev". 88351278Sdim */ 89351278Sdim if (prev == NULL) 90351278Sdim s = tlist->string; 91351278Sdim else 92351278Sdim s = prev + strlen(prev); 93351278Sdim if (s >= tlist->endstring) 94351278Sdim return (NULL); 95351278Sdim while (*s == '\0') 96351278Sdim s++; 97351278Sdim if (s >= tlist->endstring) 98351278Sdim return (NULL); 99351278Sdim return (s); 100351278Sdim} 101351278Sdim 102351278Sdim public char * 103351278Sdimback_textlist(tlist, prev) 104351278Sdim struct textlist *tlist; 105351278Sdim char *prev; 106351278Sdim{ 107351278Sdim char *s; 108351278Sdim 109351278Sdim /* 110351278Sdim * prev == NULL means return the last word in the list. 111351278Sdim * Otherwise, return the word before "prev". 112351278Sdim */ 113351278Sdim if (prev == NULL) 114351278Sdim s = tlist->endstring; 115351278Sdim else if (prev <= tlist->string) 116351278Sdim return (NULL); 117351278Sdim else 118351278Sdim s = prev - 1; 119351278Sdim while (*s == '\0') 120351278Sdim s--; 121351278Sdim if (s <= tlist->string) 122351278Sdim return (NULL); 123351278Sdim while (s[-1] != '\0' && s > tlist->string) 124351278Sdim s--; 125351278Sdim return (s); 126351278Sdim} 127351278Sdim 128351278Sdim/* 129351278Sdim * Close the current input file. 130351278Sdim */ 131351278Sdim static void 132351278Sdimclose_file() 133351278Sdim{ 134351278Sdim struct scrpos scrpos; 135351278Sdim char *filename; 136351278Sdim 137351278Sdim if (curr_ifile == NULL_IFILE) 138351278Sdim return; 139351278Sdim 140351278Sdim /* 141351278Sdim * Save the current position so that we can return to 142351278Sdim * the same position if we edit this file again. 143360784Sdim */ 144351278Sdim get_scrpos(&scrpos); 145351278Sdim if (scrpos.pos != NULL_POSITION) 146351278Sdim { 147351278Sdim store_pos(curr_ifile, &scrpos); 148351278Sdim lastmark(); 149351278Sdim } 150351278Sdim /* 151351278Sdim * Close the file descriptor, unless it is a pipe. 152351278Sdim */ 153351278Sdim ch_close(); 154351278Sdim /* 155351278Sdim * If we opened a file using an alternate name, 156351278Sdim * do special stuff to close it. 157351278Sdim */ 158351278Sdim if (curr_altfilename != NULL) 159351278Sdim { 160351278Sdim filename = unquote_file(get_filename(curr_ifile)); 161351278Sdim close_altfile(curr_altfilename, filename, curr_altpipe); 162351278Sdim free(filename); 163351278Sdim free(curr_altfilename); 164351278Sdim curr_altfilename = NULL; 165351278Sdim } 166351278Sdim curr_ifile = NULL_IFILE; 167351278Sdim} 168351278Sdim 169351278Sdim/* 170351278Sdim * Edit a new file (given its name). 171351278Sdim * Filename == "-" means standard input. 172351278Sdim * Filename == NULL means just close the current file. 173351278Sdim */ 174351278Sdim public int 175351278Sdimedit(filename) 176351278Sdim char *filename; 177351278Sdim{ 178351278Sdim if (filename == NULL) 179351278Sdim return (edit_ifile(NULL_IFILE)); 180351278Sdim return (edit_ifile(get_ifile(filename, curr_ifile))); 181351278Sdim} 182351278Sdim 183351278Sdim/* 184360784Sdim * Edit a new file (given its IFILE). 185351278Sdim * ifile == NULL means just close the current file. 186351278Sdim */ 187351278Sdim public int 188351278Sdimedit_ifile(ifile) 189360784Sdim IFILE ifile; 190351278Sdim{ 191351278Sdim int f; 192351278Sdim int answer; 193351278Sdim int no_display; 194351278Sdim int chflags; 195351278Sdim char *filename; 196351278Sdim char *open_filename; 197351278Sdim char *alt_filename; 198351278Sdim void *alt_pipe; 199351278Sdim IFILE was_curr_ifile; 200351278Sdim PARG parg; 201351278Sdim 202351278Sdim if (ifile == curr_ifile) 203351278Sdim { 204351278Sdim /* 205351278Sdim * Already have the correct file open. 206351278Sdim */ 207351278Sdim return (0); 208360784Sdim } 209360784Sdim 210351278Sdim /* 211351278Sdim * We must close the currently open file now. 212351278Sdim * This is necessary to make the open_altfile/close_altfile pairs 213351278Sdim * nest properly (or rather to avoid nesting at all). 214351278Sdim * {{ Some stupid implementations of popen() mess up if you do: 215351278Sdim * fA = popen("A"); fB = popen("B"); pclose(fA); pclose(fB); }} 216351278Sdim */ 217351278Sdim#if LOGFILE 218351278Sdim end_logfile(); 219351278Sdim#endif 220351278Sdim was_curr_ifile = save_curr_ifile(); 221351278Sdim if (curr_ifile != NULL_IFILE) 222351278Sdim { 223351278Sdim chflags = ch_getflags(); 224351278Sdim close_file(); 225351278Sdim if ((chflags & CH_HELPFILE) && held_ifile(was_curr_ifile) <= 1) 226351278Sdim { 227351278Sdim /* 228351278Sdim * Don't keep the help file in the ifile list. 229351278Sdim */ 230351278Sdim del_ifile(was_curr_ifile); 231351278Sdim was_curr_ifile = old_ifile; 232351278Sdim } 233351278Sdim } 234351278Sdim 235351278Sdim if (ifile == NULL_IFILE) 236351278Sdim { 237351278Sdim /* 238351278Sdim * No new file to open. 239351278Sdim * (Don't set old_ifile, because if you call edit_ifile(NULL), 240351278Sdim * you're supposed to have saved curr_ifile yourself, 241351278Sdim * and you'll restore it if necessary.) 242351278Sdim */ 243351278Sdim unsave_ifile(was_curr_ifile); 244351278Sdim return (0); 245351278Sdim } 246351278Sdim 247351278Sdim filename = unquote_file(get_filename(ifile)); 248351278Sdim /* 249351278Sdim * See if LESSOPEN specifies an "alternate" file to open. 250351278Sdim */ 251351278Sdim alt_pipe = NULL; 252351278Sdim alt_filename = open_altfile(filename, &f, &alt_pipe); 253351278Sdim open_filename = (alt_filename != NULL) ? alt_filename : filename; 254351278Sdim 255351278Sdim chflags = 0; 256351278Sdim if (alt_pipe != NULL) 257351278Sdim { 258351278Sdim /* 259351278Sdim * The alternate "file" is actually a pipe. 260351278Sdim * f has already been set to the file descriptor of the pipe 261351278Sdim * in the call to open_altfile above. 262351278Sdim * Keep the file descriptor open because it was opened 263351278Sdim * via popen(), and pclose() wants to close it. 264351278Sdim */ 265351278Sdim chflags |= CH_POPENED; 266351278Sdim } else if (strcmp(open_filename, "-") == 0) 267351278Sdim { 268351278Sdim /* 269351278Sdim * Use standard input. 270351278Sdim * Keep the file descriptor open because we can't reopen it. 271351278Sdim */ 272351278Sdim f = fd0; 273351278Sdim chflags |= CH_KEEPOPEN; 274351278Sdim /* 275351278Sdim * Must switch stdin to BINARY mode. 276351278Sdim */ 277351278Sdim SET_BINARY(f); 278351278Sdim#if MSDOS_COMPILER==DJGPPC 279351278Sdim /* 280351278Sdim * Setting stdin to binary by default causes 281351278Sdim * Ctrl-C to not raise SIGINT. We must undo 282351278Sdim * that side-effect. 283351278Sdim */ 284351278Sdim __djgpp_set_ctrl_c(1); 285351278Sdim#endif 286351278Sdim } else if (strcmp(open_filename, FAKE_HELPFILE) == 0) 287360784Sdim { 288351278Sdim f = -1; 289351278Sdim chflags |= CH_HELPFILE; 290351278Sdim } else if ((parg.p_string = bad_file(open_filename)) != NULL) 291351278Sdim { 292351278Sdim /* 293351278Sdim * It looks like a bad file. Don't try to open it. 294351278Sdim */ 295351278Sdim error("%s", &parg); 296360784Sdim free(parg.p_string); 297351278Sdim err1: 298351278Sdim if (alt_filename != NULL) 299351278Sdim { 300351278Sdim close_altfile(alt_filename, filename, alt_pipe); 301351278Sdim free(alt_filename); 302351278Sdim } 303351278Sdim del_ifile(ifile); 304351278Sdim free(filename); 305351278Sdim /* 306351278Sdim * Re-open the current file. 307351278Sdim */ 308351278Sdim reedit_ifile(was_curr_ifile); 309351278Sdim return (1); 310351278Sdim } else if ((f = open(open_filename, OPEN_READ)) < 0) 311351278Sdim { 312351278Sdim /* 313351278Sdim * Got an error trying to open it. 314351278Sdim */ 315351278Sdim parg.p_string = errno_message(filename); 316351278Sdim error("%s", &parg); 317351278Sdim free(parg.p_string); 318351278Sdim goto err1; 319351278Sdim } else 320351278Sdim { 321351278Sdim chflags |= CH_CANSEEK; 322351278Sdim if (!force_open && !opened(ifile) && bin_file(f)) 323351278Sdim { 324351278Sdim /* 325351278Sdim * Looks like a binary file. 326351278Sdim * Ask user if we should proceed. 327351278Sdim */ 328351278Sdim parg.p_string = filename; 329351278Sdim answer = query("\"%s\" may be a binary file. See it anyway? ", 330351278Sdim &parg); 331351278Sdim if (answer != 'y' && answer != 'Y') 332351278Sdim { 333351278Sdim close(f); 334351278Sdim goto err1; 335351278Sdim } 336351278Sdim } 337351278Sdim } 338351278Sdim 339351278Sdim /* 340351278Sdim * Get the new ifile. 341351278Sdim * Get the saved position for the file. 342351278Sdim */ 343351278Sdim if (was_curr_ifile != NULL_IFILE) 344351278Sdim { 345351278Sdim old_ifile = was_curr_ifile; 346351278Sdim unsave_ifile(was_curr_ifile); 347351278Sdim } 348351278Sdim curr_ifile = ifile; 349351278Sdim curr_altfilename = alt_filename; 350351278Sdim curr_altpipe = alt_pipe; 351351278Sdim set_open(curr_ifile); /* File has been opened */ 352351278Sdim get_pos(curr_ifile, &initial_scrpos); 353351278Sdim new_file = TRUE; 354351278Sdim ch_init(f, chflags); 355351278Sdim 356351278Sdim if (!(chflags & CH_HELPFILE)) 357351278Sdim { 358351278Sdim#if LOGFILE 359351278Sdim if (namelogfile != NULL && is_tty) 360351278Sdim use_logfile(namelogfile); 361351278Sdim#endif 362351278Sdim if (every_first_cmd != NULL) 363351278Sdim ungetsc(every_first_cmd); 364351278Sdim } 365351278Sdim 366351278Sdim no_display = !any_display; 367351278Sdim flush(); 368351278Sdim any_display = TRUE; 369351278Sdim 370351278Sdim if (is_tty) 371351278Sdim { 372351278Sdim /* 373351278Sdim * Output is to a real tty. 374351278Sdim */ 375351278Sdim 376351278Sdim /* 377351278Sdim * Indicate there is nothing displayed yet. 378351278Sdim */ 379351278Sdim pos_clear(); 380351278Sdim clr_linenum(); 381351278Sdim#if HILITE_SEARCH 382351278Sdim clr_hilite(); 383351278Sdim#endif 384351278Sdim cmd_addhist(ml_examine, filename); 385351278Sdim if (no_display && errmsgs > 0) 386351278Sdim { 387351278Sdim /* 388351278Sdim * We displayed some messages on error output 389351278Sdim * (file descriptor 2; see error() function). 390351278Sdim * Before erasing the screen contents, 391351278Sdim * display the file name and wait for a keystroke. 392351278Sdim */ 393351278Sdim parg.p_string = filename; 394351278Sdim error("%s", &parg); 395351278Sdim } 396351278Sdim } 397351278Sdim free(filename); 398351278Sdim return (0); 399351278Sdim} 400351278Sdim 401351278Sdim/* 402351278Sdim * Edit a space-separated list of files. 403351278Sdim * For each filename in the list, enter it into the ifile list. 404351278Sdim * Then edit the first one. 405351278Sdim */ 406351278Sdim public int 407351278Sdimedit_list(filelist) 408351278Sdim char *filelist; 409351278Sdim{ 410351278Sdim IFILE save_ifile; 411351278Sdim char *good_filename; 412351278Sdim char *filename; 413351278Sdim char *gfilelist; 414351278Sdim char *gfilename; 415351278Sdim struct textlist tl_files; 416351278Sdim struct textlist tl_gfiles; 417351278Sdim 418351278Sdim save_ifile = save_curr_ifile(); 419351278Sdim good_filename = NULL; 420351278Sdim 421351278Sdim /* 422351278Sdim * Run thru each filename in the list. 423351278Sdim * Try to glob the filename. 424351278Sdim * If it doesn't expand, just try to open the filename. 425351278Sdim * If it does expand, try to open each name in that list. 426351278Sdim */ 427351278Sdim init_textlist(&tl_files, filelist); 428351278Sdim filename = NULL; 429351278Sdim while ((filename = forw_textlist(&tl_files, filename)) != NULL) 430351278Sdim { 431351278Sdim gfilelist = lglob(filename); 432351278Sdim init_textlist(&tl_gfiles, gfilelist); 433351278Sdim gfilename = NULL; 434351278Sdim while ((gfilename = forw_textlist(&tl_gfiles, gfilename)) != NULL) 435351278Sdim { 436351278Sdim if (edit(gfilename) == 0 && good_filename == NULL) 437351278Sdim good_filename = get_filename(curr_ifile); 438351278Sdim } 439351278Sdim free(gfilelist); 440351278Sdim } 441351278Sdim /* 442351278Sdim * Edit the first valid filename in the list. 443351278Sdim */ 444351278Sdim if (good_filename == NULL) 445351278Sdim { 446351278Sdim unsave_ifile(save_ifile); 447351278Sdim return (1); 448351278Sdim } 449360784Sdim if (get_ifile(good_filename, curr_ifile) == curr_ifile) 450351278Sdim { 451351278Sdim /* 452351278Sdim * Trying to edit the current file; don't reopen it. 453351278Sdim */ 454351278Sdim unsave_ifile(save_ifile); 455351278Sdim return (0); 456351278Sdim } 457351278Sdim reedit_ifile(save_ifile); 458351278Sdim return (edit(good_filename)); 459351278Sdim} 460351278Sdim 461351278Sdim/* 462351278Sdim * Edit the first file in the command line (ifile) list. 463351278Sdim */ 464351278Sdim public int 465351278Sdimedit_first() 466351278Sdim{ 467351278Sdim curr_ifile = NULL_IFILE; 468351278Sdim return (edit_next(1)); 469351278Sdim} 470351278Sdim 471351278Sdim/* 472351278Sdim * Edit the last file in the command line (ifile) list. 473351278Sdim */ 474351278Sdim public int 475351278Sdimedit_last() 476351278Sdim{ 477351278Sdim curr_ifile = NULL_IFILE; 478351278Sdim return (edit_prev(1)); 479351278Sdim} 480351278Sdim 481351278Sdim 482351278Sdim/* 483351278Sdim * Edit the next or previous file in the command line (ifile) list. 484351278Sdim */ 485351278Sdim static int 486351278Sdimedit_istep(h, n, dir) 487351278Sdim IFILE h; 488351278Sdim int n; 489351278Sdim int dir; 490351278Sdim{ 491351278Sdim IFILE next; 492351278Sdim 493351278Sdim /* 494351278Sdim * Skip n filenames, then try to edit each filename. 495351278Sdim */ 496351278Sdim for (;;) 497351278Sdim { 498351278Sdim next = (dir > 0) ? next_ifile(h) : prev_ifile(h); 499351278Sdim if (--n < 0) 500351278Sdim { 501351278Sdim if (edit_ifile(h) == 0) 502351278Sdim break; 503351278Sdim } 504351278Sdim if (next == NULL_IFILE) 505351278Sdim { 506351278Sdim /* 507 * Reached end of the ifile list. 508 */ 509 return (1); 510 } 511 if (ABORT_SIGS()) 512 { 513 /* 514 * Interrupt breaks out, if we're in a long 515 * list of files that can't be opened. 516 */ 517 return (1); 518 } 519 h = next; 520 } 521 /* 522 * Found a file that we can edit. 523 */ 524 return (0); 525} 526 527 static int 528edit_inext(h, n) 529 IFILE h; 530 int n; 531{ 532 return (edit_istep(h, n, 1)); 533} 534 535 public int 536edit_next(n) 537 int n; 538{ 539 return edit_istep(curr_ifile, n, 1); 540} 541 542 static int 543edit_iprev(h, n) 544 IFILE h; 545 int n; 546{ 547 return (edit_istep(h, n, -1)); 548} 549 550 public int 551edit_prev(n) 552 int n; 553{ 554 return edit_istep(curr_ifile, n, -1); 555} 556 557/* 558 * Edit a specific file in the command line (ifile) list. 559 */ 560 public int 561edit_index(n) 562 int n; 563{ 564 IFILE h; 565 566 h = NULL_IFILE; 567 do 568 { 569 if ((h = next_ifile(h)) == NULL_IFILE) 570 { 571 /* 572 * Reached end of the list without finding it. 573 */ 574 return (1); 575 } 576 } while (get_index(h) != n); 577 578 return (edit_ifile(h)); 579} 580 581 public IFILE 582save_curr_ifile() 583{ 584 if (curr_ifile != NULL_IFILE) 585 hold_ifile(curr_ifile, 1); 586 return (curr_ifile); 587} 588 589 public void 590unsave_ifile(save_ifile) 591 IFILE save_ifile; 592{ 593 if (save_ifile != NULL_IFILE) 594 hold_ifile(save_ifile, -1); 595} 596 597/* 598 * Reedit the ifile which was previously open. 599 */ 600 public void 601reedit_ifile(save_ifile) 602 IFILE save_ifile; 603{ 604 IFILE next; 605 IFILE prev; 606 607 /* 608 * Try to reopen the ifile. 609 * Note that opening it may fail (maybe the file was removed), 610 * in which case the ifile will be deleted from the list. 611 * So save the next and prev ifiles first. 612 */ 613 unsave_ifile(save_ifile); 614 next = next_ifile(save_ifile); 615 prev = prev_ifile(save_ifile); 616 if (edit_ifile(save_ifile) == 0) 617 return; 618 /* 619 * If can't reopen it, open the next input file in the list. 620 */ 621 if (next != NULL_IFILE && edit_inext(next, 0) == 0) 622 return; 623 /* 624 * If can't open THAT one, open the previous input file in the list. 625 */ 626 if (prev != NULL_IFILE && edit_iprev(prev, 0) == 0) 627 return; 628 /* 629 * If can't even open that, we're stuck. Just quit. 630 */ 631 quit(QUIT_ERROR); 632} 633 634/* 635 * Edit standard input. 636 */ 637 public int 638edit_stdin() 639{ 640 if (isatty(fd0)) 641 { 642 error("Missing filename (\"less --help\" for help)", NULL_PARG); 643 quit(QUIT_OK); 644 } 645 return (edit("-")); 646} 647 648/* 649 * Copy a file directly to standard output. 650 * Used if standard output is not a tty. 651 */ 652 public void 653cat_file() 654{ 655 register int c; 656 657 while ((c = ch_forw_get()) != EOI) 658 putchr(c); 659 flush(); 660} 661 662#if LOGFILE 663 664/* 665 * If the user asked for a log file and our input file 666 * is standard input, create the log file. 667 * We take care not to blindly overwrite an existing file. 668 */ 669 public void 670use_logfile(filename) 671 char *filename; 672{ 673 register int exists; 674 register int answer; 675 PARG parg; 676 677 if (ch_getflags() & CH_CANSEEK) 678 /* 679 * Can't currently use a log file on a file that can seek. 680 */ 681 return; 682 683 /* 684 * {{ We could use access() here. }} 685 */ 686 filename = unquote_file(filename); 687 exists = open(filename, OPEN_READ); 688 close(exists); 689 exists = (exists >= 0); 690 691 /* 692 * Decide whether to overwrite the log file or append to it. 693 * If it doesn't exist we "overwrite" it. 694 */ 695 if (!exists || force_logfile) 696 { 697 /* 698 * Overwrite (or create) the log file. 699 */ 700 answer = 'O'; 701 } else 702 { 703 /* 704 * Ask user what to do. 705 */ 706 parg.p_string = filename; 707 answer = query("Warning: \"%s\" exists; Overwrite, Append or Don't log? ", &parg); 708 } 709 710loop: 711 switch (answer) 712 { 713 case 'O': case 'o': 714 /* 715 * Overwrite: create the file. 716 */ 717 logfile = creat(filename, 0644); 718 break; 719 case 'A': case 'a': 720 /* 721 * Append: open the file and seek to the end. 722 */ 723 logfile = open(filename, OPEN_APPEND); 724 if (lseek(logfile, (off_t)0, 2) == BAD_LSEEK) 725 { 726 close(logfile); 727 logfile = -1; 728 } 729 break; 730 case 'D': case 'd': 731 /* 732 * Don't do anything. 733 */ 734 free(filename); 735 return; 736 case 'q': 737 quit(QUIT_OK); 738 /*NOTREACHED*/ 739 default: 740 /* 741 * Eh? 742 */ 743 answer = query("Overwrite, Append, or Don't log? (Type \"O\", \"A\", \"D\" or \"q\") ", NULL_PARG); 744 goto loop; 745 } 746 747 if (logfile < 0) 748 { 749 /* 750 * Error in opening logfile. 751 */ 752 parg.p_string = filename; 753 error("Cannot write to \"%s\"", &parg); 754 free(filename); 755 return; 756 } 757 free(filename); 758 SET_BINARY(logfile); 759} 760 761#endif 762