[BACK]Return to edit.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / less

Annotation of src/usr.bin/less/edit.c, Revision 1.6

1.1       etheisen    1: /*
1.4       millert     2:  * Copyright (C) 1984-2002  Mark Nudelman
1.1       etheisen    3:  *
1.4       millert     4:  * You may distribute under the terms of either the GNU General Public
                      5:  * License or the Less License, as specified in the README file.
1.1       etheisen    6:  *
1.4       millert     7:  * For more information about less, or for information on how to
                      8:  * contact the author, see the README file.
1.1       etheisen    9:  */
                     10:
                     11:
                     12: #include "less.h"
                     13:
                     14: public int fd0 = 0;
                     15:
                     16: extern int new_file;
                     17: extern int errmsgs;
                     18: extern int cbufs;
                     19: extern char *every_first_cmd;
                     20: extern int any_display;
                     21: extern int force_open;
                     22: extern int is_tty;
1.4       millert    23: extern int sigs;
1.1       etheisen   24: extern IFILE curr_ifile;
                     25: extern IFILE old_ifile;
                     26: extern struct scrpos initial_scrpos;
1.4       millert    27: extern void constant *ml_examine;
                     28: #if SPACES_IN_FILENAMES
                     29: extern char openquote;
                     30: extern char closequote;
                     31: #endif
1.1       etheisen   32:
                     33: #if LOGFILE
                     34: extern int logfile;
                     35: extern int force_logfile;
                     36: extern char *namelogfile;
                     37: #endif
                     38:
                     39: char *curr_altfilename = NULL;
                     40: static void *curr_altpipe;
                     41:
                     42:
                     43: /*
                     44:  * Textlist functions deal with a list of words separated by spaces.
                     45:  * init_textlist sets up a textlist structure.
                     46:  * forw_textlist uses that structure to iterate thru the list of
                     47:  * words, returning each one as a standard null-terminated string.
                     48:  * back_textlist does the same, but runs thru the list backwards.
                     49:  */
                     50:        public void
                     51: init_textlist(tlist, str)
                     52:        struct textlist *tlist;
                     53:        char *str;
                     54: {
                     55:        char *s;
1.4       millert    56: #if SPACES_IN_FILENAMES
                     57:        int meta_quoted = 0;
                     58:        int delim_quoted = 0;
                     59:        char *esc = get_meta_escape();
                     60:        int esclen = strlen(esc);
                     61: #endif
1.1       etheisen   62:
                     63:        tlist->string = skipsp(str);
                     64:        tlist->endstring = tlist->string + strlen(tlist->string);
                     65:        for (s = str;  s < tlist->endstring;  s++)
                     66:        {
1.4       millert    67: #if SPACES_IN_FILENAMES
                     68:                if (meta_quoted)
                     69:                {
                     70:                        meta_quoted = 0;
                     71:                } else if (esclen > 0 && s + esclen < tlist->endstring &&
                     72:                           strncmp(s, esc, esclen) == 0)
                     73:                {
                     74:                        meta_quoted = 1;
                     75:                        s += esclen - 1;
                     76:                } else if (delim_quoted)
                     77:                {
                     78:                        if (*s == closequote)
                     79:                                delim_quoted = 0;
                     80:                } else /* (!delim_quoted) */
                     81:                {
                     82:                        if (*s == openquote)
                     83:                                delim_quoted = 1;
                     84:                        else if (*s == ' ')
                     85:                                *s = '\0';
                     86:                }
                     87: #else
1.1       etheisen   88:                if (*s == ' ')
                     89:                        *s = '\0';
1.4       millert    90: #endif
1.1       etheisen   91:        }
                     92: }
                     93:
                     94:        public char *
                     95: forw_textlist(tlist, prev)
                     96:        struct textlist *tlist;
                     97:        char *prev;
                     98: {
                     99:        char *s;
                    100:
                    101:        /*
                    102:         * prev == NULL means return the first word in the list.
                    103:         * Otherwise, return the word after "prev".
                    104:         */
                    105:        if (prev == NULL)
                    106:                s = tlist->string;
                    107:        else
                    108:                s = prev + strlen(prev);
                    109:        if (s >= tlist->endstring)
                    110:                return (NULL);
                    111:        while (*s == '\0')
                    112:                s++;
                    113:        if (s >= tlist->endstring)
                    114:                return (NULL);
                    115:        return (s);
                    116: }
                    117:
                    118:        public char *
                    119: back_textlist(tlist, prev)
                    120:        struct textlist *tlist;
                    121:        char *prev;
                    122: {
                    123:        char *s;
                    124:
                    125:        /*
                    126:         * prev == NULL means return the last word in the list.
                    127:         * Otherwise, return the word before "prev".
                    128:         */
                    129:        if (prev == NULL)
                    130:                s = tlist->endstring;
                    131:        else if (prev <= tlist->string)
                    132:                return (NULL);
                    133:        else
                    134:                s = prev - 1;
                    135:        while (*s == '\0')
                    136:                s--;
                    137:        if (s <= tlist->string)
                    138:                return (NULL);
                    139:        while (s[-1] != '\0' && s > tlist->string)
                    140:                s--;
                    141:        return (s);
                    142: }
                    143:
                    144: /*
                    145:  * Close the current input file.
                    146:  */
                    147:        static void
                    148: close_file()
                    149: {
                    150:        struct scrpos scrpos;
                    151:
                    152:        if (curr_ifile == NULL_IFILE)
                    153:                return;
1.4       millert   154:
1.1       etheisen  155:        /*
                    156:         * Save the current position so that we can return to
                    157:         * the same position if we edit this file again.
                    158:         */
                    159:        get_scrpos(&scrpos);
                    160:        if (scrpos.pos != NULL_POSITION)
                    161:        {
                    162:                store_pos(curr_ifile, &scrpos);
                    163:                lastmark();
                    164:        }
                    165:        /*
                    166:         * Close the file descriptor, unless it is a pipe.
                    167:         */
                    168:        ch_close();
                    169:        /*
                    170:         * If we opened a file using an alternate name,
                    171:         * do special stuff to close it.
                    172:         */
                    173:        if (curr_altfilename != NULL)
                    174:        {
                    175:                close_altfile(curr_altfilename, get_filename(curr_ifile),
1.4       millert   176:                                curr_altpipe);
1.1       etheisen  177:                free(curr_altfilename);
                    178:                curr_altfilename = NULL;
                    179:        }
                    180:        curr_ifile = NULL_IFILE;
                    181: }
                    182:
                    183: /*
                    184:  * Edit a new file (given its name).
                    185:  * Filename == "-" means standard input.
                    186:  * Filename == NULL means just close the current file.
                    187:  */
                    188:        public int
                    189: edit(filename)
                    190:        char *filename;
                    191: {
                    192:        if (filename == NULL)
                    193:                return (edit_ifile(NULL_IFILE));
                    194:        return (edit_ifile(get_ifile(filename, curr_ifile)));
                    195: }
                    196:
                    197: /*
                    198:  * Edit a new file (given its IFILE).
                    199:  * ifile == NULL means just close the current file.
                    200:  */
                    201:        public int
                    202: edit_ifile(ifile)
                    203:        IFILE ifile;
                    204: {
                    205:        int f;
                    206:        int answer;
                    207:        int no_display;
                    208:        int chflags;
                    209:        char *filename;
                    210:        char *open_filename;
1.4       millert   211:        char *qopen_filename;
1.1       etheisen  212:        char *alt_filename;
                    213:        void *alt_pipe;
                    214:        IFILE was_curr_ifile;
                    215:        PARG parg;
                    216:
                    217:        if (ifile == curr_ifile)
                    218:        {
                    219:                /*
                    220:                 * Already have the correct file open.
                    221:                 */
                    222:                return (0);
                    223:        }
                    224:
                    225:        /*
                    226:         * We must close the currently open file now.
                    227:         * This is necessary to make the open_altfile/close_altfile pairs
                    228:         * nest properly (or rather to avoid nesting at all).
                    229:         * {{ Some stupid implementations of popen() mess up if you do:
                    230:         *    fA = popen("A"); fB = popen("B"); pclose(fA); pclose(fB); }}
                    231:         */
                    232: #if LOGFILE
                    233:        end_logfile();
                    234: #endif
1.4       millert   235:        was_curr_ifile = save_curr_ifile();
1.1       etheisen  236:        if (curr_ifile != NULL_IFILE)
                    237:        {
1.4       millert   238:                chflags = ch_getflags();
1.1       etheisen  239:                close_file();
                    240:        }
                    241:
                    242:        if (ifile == NULL_IFILE)
                    243:        {
                    244:                /*
                    245:                 * No new file to open.
                    246:                 * (Don't set old_ifile, because if you call edit_ifile(NULL),
                    247:                 *  you're supposed to have saved curr_ifile yourself,
                    248:                 *  and you'll restore it if necessary.)
                    249:                 */
1.4       millert   250:                unsave_ifile(was_curr_ifile);
1.1       etheisen  251:                return (0);
                    252:        }
                    253:
1.4       millert   254:        filename = save(get_filename(ifile));
1.1       etheisen  255:        /*
                    256:         * See if LESSOPEN specifies an "alternate" file to open.
                    257:         */
                    258:        alt_pipe = NULL;
                    259:        alt_filename = open_altfile(filename, &f, &alt_pipe);
                    260:        open_filename = (alt_filename != NULL) ? alt_filename : filename;
1.4       millert   261:        qopen_filename = shell_unquote(open_filename);
1.1       etheisen  262:
                    263:        chflags = 0;
                    264:        if (alt_pipe != NULL)
                    265:        {
                    266:                /*
                    267:                 * The alternate "file" is actually a pipe.
                    268:                 * f has already been set to the file descriptor of the pipe
                    269:                 * in the call to open_altfile above.
                    270:                 * Keep the file descriptor open because it was opened
                    271:                 * via popen(), and pclose() wants to close it.
                    272:                 */
                    273:                chflags |= CH_POPENED;
                    274:        } else if (strcmp(open_filename, "-") == 0)
                    275:        {
                    276:                /*
                    277:                 * Use standard input.
                    278:                 * Keep the file descriptor open because we can't reopen it.
                    279:                 */
                    280:                f = fd0;
                    281:                chflags |= CH_KEEPOPEN;
1.4       millert   282:                /*
                    283:                 * Must switch stdin to BINARY mode.
                    284:                 */
                    285:                SET_BINARY(f);
                    286: #if MSDOS_COMPILER==DJGPPC
                    287:                /*
                    288:                 * Setting stdin to binary by default causes
                    289:                 * Ctrl-C to not raise SIGINT.  We must undo
                    290:                 * that side-effect.
                    291:                 */
                    292:                __djgpp_set_ctrl_c(1);
                    293: #endif
1.1       etheisen  294:        } else if ((parg.p_string = bad_file(open_filename)) != NULL)
                    295:        {
                    296:                /*
                    297:                 * It looks like a bad file.  Don't try to open it.
                    298:                 */
                    299:                error("%s", &parg);
                    300:                free(parg.p_string);
                    301:            err1:
                    302:                if (alt_filename != NULL)
                    303:                {
                    304:                        close_altfile(alt_filename, filename, alt_pipe);
                    305:                        free(alt_filename);
                    306:                }
                    307:                del_ifile(ifile);
1.4       millert   308:                free(qopen_filename);
                    309:                free(filename);
1.1       etheisen  310:                /*
                    311:                 * Re-open the current file.
                    312:                 */
1.4       millert   313:                reedit_ifile(was_curr_ifile);
1.1       etheisen  314:                return (1);
1.4       millert   315:        } else if ((f = open(qopen_filename, OPEN_READ)) < 0)
1.1       etheisen  316:        {
                    317:                /*
                    318:                 * Got an error trying to open it.
                    319:                 */
                    320:                parg.p_string = errno_message(filename);
                    321:                error("%s", &parg);
                    322:                free(parg.p_string);
                    323:                goto err1;
1.4       millert   324:        } else
1.1       etheisen  325:        {
1.4       millert   326:                chflags |= CH_CANSEEK;
                    327:                if (!force_open && !opened(ifile) && bin_file(f))
1.1       etheisen  328:                {
1.4       millert   329:                        /*
                    330:                         * Looks like a binary file.
                    331:                         * Ask user if we should proceed.
                    332:                         */
                    333:                        parg.p_string = filename;
                    334:                        answer = query("\"%s\" may be a binary file.  See it anyway? ",
                    335:                                &parg);
                    336:                        if (answer != 'y' && answer != 'Y')
                    337:                        {
                    338:                                close(f);
                    339:                                goto err1;
                    340:                        }
1.1       etheisen  341:                }
                    342:        }
1.4       millert   343:        free(qopen_filename);
1.1       etheisen  344:
                    345:        /*
                    346:         * Get the new ifile.
                    347:         * Get the saved position for the file.
                    348:         */
                    349:        if (was_curr_ifile != NULL_IFILE)
1.4       millert   350:        {
1.1       etheisen  351:                old_ifile = was_curr_ifile;
1.4       millert   352:                unsave_ifile(was_curr_ifile);
                    353:        }
1.1       etheisen  354:        curr_ifile = ifile;
                    355:        curr_altfilename = alt_filename;
                    356:        curr_altpipe = alt_pipe;
                    357:        set_open(curr_ifile); /* File has been opened */
                    358:        get_pos(curr_ifile, &initial_scrpos);
                    359:        new_file = TRUE;
                    360:        ch_init(f, chflags);
1.4       millert   361:
1.1       etheisen  362: #if LOGFILE
1.5       millert   363:        if (namelogfile != NULL && is_tty)
                    364:                use_logfile(namelogfile);
1.1       etheisen  365: #endif
1.5       millert   366:        if (every_first_cmd != NULL)
                    367:                ungetsc(every_first_cmd);
1.1       etheisen  368:
                    369:        no_display = !any_display;
                    370:        flush();
                    371:        any_display = TRUE;
                    372:
                    373:        if (is_tty)
                    374:        {
                    375:                /*
                    376:                 * Output is to a real tty.
                    377:                 */
                    378:
                    379:                /*
                    380:                 * Indicate there is nothing displayed yet.
                    381:                 */
                    382:                pos_clear();
                    383:                clr_linenum();
                    384: #if HILITE_SEARCH
                    385:                clr_hilite();
                    386: #endif
1.4       millert   387:                cmd_addhist(ml_examine, filename);
1.1       etheisen  388:                if (no_display && errmsgs > 0)
                    389:                {
                    390:                        /*
                    391:                         * We displayed some messages on error output
                    392:                         * (file descriptor 2; see error() function).
                    393:                         * Before erasing the screen contents,
                    394:                         * display the file name and wait for a keystroke.
                    395:                         */
                    396:                        parg.p_string = filename;
                    397:                        error("%s", &parg);
                    398:                }
                    399:        }
1.4       millert   400:        free(filename);
1.1       etheisen  401:        return (0);
                    402: }
                    403:
                    404: /*
                    405:  * Edit a space-separated list of files.
                    406:  * For each filename in the list, enter it into the ifile list.
                    407:  * Then edit the first one.
                    408:  */
                    409:        public int
                    410: edit_list(filelist)
                    411:        char *filelist;
                    412: {
1.4       millert   413:        IFILE save_ifile;
1.1       etheisen  414:        char *good_filename;
                    415:        char *filename;
                    416:        char *gfilelist;
                    417:        char *gfilename;
                    418:        struct textlist tl_files;
                    419:        struct textlist tl_gfiles;
                    420:
1.4       millert   421:        save_ifile = save_curr_ifile();
1.1       etheisen  422:        good_filename = NULL;
                    423:
                    424:        /*
                    425:         * Run thru each filename in the list.
                    426:         * Try to glob the filename.
                    427:         * If it doesn't expand, just try to open the filename.
                    428:         * If it does expand, try to open each name in that list.
                    429:         */
                    430:        init_textlist(&tl_files, filelist);
                    431:        filename = NULL;
                    432:        while ((filename = forw_textlist(&tl_files, filename)) != NULL)
                    433:        {
1.4       millert   434:                gfilelist = lglob(filename);
1.1       etheisen  435:                init_textlist(&tl_gfiles, gfilelist);
                    436:                gfilename = NULL;
                    437:                while ((gfilename = forw_textlist(&tl_gfiles, gfilename)) != NULL)
                    438:                {
                    439:                        if (edit(gfilename) == 0 && good_filename == NULL)
                    440:                                good_filename = get_filename(curr_ifile);
                    441:                }
                    442:                free(gfilelist);
                    443:        }
                    444:        /*
                    445:         * Edit the first valid filename in the list.
                    446:         */
                    447:        if (good_filename == NULL)
1.4       millert   448:        {
                    449:                unsave_ifile(save_ifile);
1.1       etheisen  450:                return (1);
1.4       millert   451:        }
1.1       etheisen  452:        if (get_ifile(good_filename, curr_ifile) == curr_ifile)
1.4       millert   453:        {
1.1       etheisen  454:                /*
                    455:                 * Trying to edit the current file; don't reopen it.
                    456:                 */
1.4       millert   457:                unsave_ifile(save_ifile);
1.1       etheisen  458:                return (0);
1.4       millert   459:        }
                    460:        reedit_ifile(save_ifile);
1.1       etheisen  461:        return (edit(good_filename));
                    462: }
                    463:
                    464: /*
                    465:  * Edit the first file in the command line (ifile) list.
                    466:  */
                    467:        public int
                    468: edit_first()
                    469: {
                    470:        curr_ifile = NULL_IFILE;
                    471:        return (edit_next(1));
                    472: }
                    473:
                    474: /*
                    475:  * Edit the last file in the command line (ifile) list.
                    476:  */
                    477:        public int
                    478: edit_last()
                    479: {
                    480:        curr_ifile = NULL_IFILE;
                    481:        return (edit_prev(1));
                    482: }
                    483:
                    484:
                    485: /*
1.4       millert   486:  * Edit the next or previous file in the command line (ifile) list.
1.1       etheisen  487:  */
1.4       millert   488:        static int
                    489: edit_istep(h, n, dir)
                    490:        IFILE h;
1.1       etheisen  491:        int n;
1.4       millert   492:        int dir;
1.1       etheisen  493: {
                    494:        IFILE next;
                    495:
                    496:        /*
                    497:         * Skip n filenames, then try to edit each filename.
                    498:         */
                    499:        for (;;)
                    500:        {
1.4       millert   501:                next = (dir > 0) ? next_ifile(h) : prev_ifile(h);
1.1       etheisen  502:                if (--n < 0)
                    503:                {
                    504:                        if (edit_ifile(h) == 0)
                    505:                                break;
                    506:                }
                    507:                if (next == NULL_IFILE)
                    508:                {
                    509:                        /*
                    510:                         * Reached end of the ifile list.
                    511:                         */
                    512:                        return (1);
                    513:                }
1.4       millert   514:                if (ABORT_SIGS())
                    515:                {
                    516:                        /*
                    517:                         * Interrupt breaks out, if we're in a long
                    518:                         * list of files that can't be opened.
                    519:                         */
                    520:                        return (1);
                    521:                }
1.1       etheisen  522:                h = next;
                    523:        }
                    524:        /*
                    525:         * Found a file that we can edit.
                    526:         */
                    527:        return (0);
                    528: }
                    529:
1.4       millert   530:        static int
                    531: edit_inext(h, n)
                    532:        IFILE h;
                    533:        int n;
                    534: {
                    535:        return (edit_istep(h, n, 1));
                    536: }
                    537:
1.1       etheisen  538:        public int
1.4       millert   539: edit_next(n)
1.1       etheisen  540:        int n;
                    541: {
1.4       millert   542:        return edit_istep(curr_ifile, n, 1);
                    543: }
                    544:
                    545:        static int
                    546: edit_iprev(h, n)
1.1       etheisen  547:        IFILE h;
1.4       millert   548:        int n;
                    549: {
                    550:        return (edit_istep(h, n, -1));
                    551: }
1.1       etheisen  552:
1.4       millert   553:        public int
                    554: edit_prev(n)
                    555:        int n;
                    556: {
                    557:        return edit_istep(curr_ifile, n, -1);
1.1       etheisen  558: }
                    559:
                    560: /*
                    561:  * Edit a specific file in the command line (ifile) list.
                    562:  */
                    563:        public int
                    564: edit_index(n)
                    565:        int n;
                    566: {
                    567:        IFILE h;
                    568:
                    569:        h = NULL_IFILE;
                    570:        do
                    571:        {
                    572:                if ((h = next_ifile(h)) == NULL_IFILE)
                    573:                {
                    574:                        /*
                    575:                         * Reached end of the list without finding it.
                    576:                         */
                    577:                        return (1);
                    578:                }
                    579:        } while (get_index(h) != n);
                    580:
                    581:        return (edit_ifile(h));
                    582: }
                    583:
1.4       millert   584:        public IFILE
                    585: save_curr_ifile()
                    586: {
                    587:        if (curr_ifile != NULL_IFILE)
                    588:                hold_ifile(curr_ifile, 1);
                    589:        return (curr_ifile);
                    590: }
                    591:
                    592:        public void
                    593: unsave_ifile(save_ifile)
                    594:        IFILE save_ifile;
                    595: {
                    596:        if (save_ifile != NULL_IFILE)
                    597:                hold_ifile(save_ifile, -1);
                    598: }
                    599:
                    600: /*
                    601:  * Reedit the ifile which was previously open.
                    602:  */
                    603:        public void
                    604: reedit_ifile(save_ifile)
                    605:        IFILE save_ifile;
                    606: {
                    607:        IFILE next;
                    608:        IFILE prev;
                    609:
                    610:        /*
                    611:         * Try to reopen the ifile.
                    612:         * Note that opening it may fail (maybe the file was removed),
                    613:         * in which case the ifile will be deleted from the list.
                    614:         * So save the next and prev ifiles first.
                    615:         */
                    616:        unsave_ifile(save_ifile);
                    617:        next = next_ifile(save_ifile);
                    618:        prev = prev_ifile(save_ifile);
                    619:        if (edit_ifile(save_ifile) == 0)
                    620:                return;
                    621:        /*
                    622:         * If can't reopen it, open the next input file in the list.
                    623:         */
                    624:        if (next != NULL_IFILE && edit_inext(next, 0) == 0)
                    625:                return;
                    626:        /*
                    627:         * If can't open THAT one, open the previous input file in the list.
                    628:         */
                    629:        if (prev != NULL_IFILE && edit_iprev(prev, 0) == 0)
                    630:                return;
                    631:        /*
                    632:         * If can't even open that, we're stuck.  Just quit.
                    633:         */
                    634:        quit(QUIT_ERROR);
                    635: }
                    636:
1.1       etheisen  637: /*
                    638:  * Edit standard input.
                    639:  */
                    640:        public int
                    641: edit_stdin()
                    642: {
                    643:        if (isatty(fd0))
                    644:        {
1.4       millert   645:                error("Missing filename (\"less --help\" for help)", NULL_PARG);
1.1       etheisen  646:                quit(QUIT_OK);
                    647:        }
                    648:        return (edit("-"));
                    649: }
                    650:
                    651: /*
                    652:  * Copy a file directly to standard output.
                    653:  * Used if standard output is not a tty.
                    654:  */
                    655:        public void
                    656: cat_file()
                    657: {
1.4       millert   658:        register int c;
1.1       etheisen  659:
                    660:        while ((c = ch_forw_get()) != EOI)
                    661:                putchr(c);
                    662:        flush();
                    663: }
                    664:
                    665: #if LOGFILE
                    666:
                    667: /*
                    668:  * If the user asked for a log file and our input file
                    669:  * is standard input, create the log file.
                    670:  * We take care not to blindly overwrite an existing file.
                    671:  */
                    672:        public void
                    673: use_logfile(filename)
                    674:        char *filename;
                    675: {
1.4       millert   676:        register int exists;
                    677:        register int answer;
1.1       etheisen  678:        PARG parg;
                    679:
                    680:        if (ch_getflags() & CH_CANSEEK)
                    681:                /*
                    682:                 * Can't currently use a log file on a file that can seek.
                    683:                 */
                    684:                return;
                    685:
                    686:        /*
                    687:         * {{ We could use access() here. }}
                    688:         */
1.4       millert   689:        filename = shell_unquote(filename);
1.1       etheisen  690:        exists = open(filename, OPEN_READ);
                    691:        close(exists);
                    692:        exists = (exists >= 0);
                    693:
                    694:        /*
                    695:         * Decide whether to overwrite the log file or append to it.
                    696:         * If it doesn't exist we "overwrite" it.
                    697:         */
                    698:        if (!exists || force_logfile)
                    699:        {
                    700:                /*
                    701:                 * Overwrite (or create) the log file.
                    702:                 */
                    703:                answer = 'O';
                    704:        } else
                    705:        {
                    706:                /*
                    707:                 * Ask user what to do.
                    708:                 */
                    709:                parg.p_string = filename;
                    710:                answer = query("Warning: \"%s\" exists; Overwrite, Append or Don't log? ", &parg);
                    711:        }
                    712:
                    713: loop:
                    714:        switch (answer)
                    715:        {
                    716:        case 'O': case 'o':
                    717:                /*
                    718:                 * Overwrite: create the file.
                    719:                 */
                    720:                logfile = creat(filename, 0644);
                    721:                break;
                    722:        case 'A': case 'a':
                    723:                /*
                    724:                 * Append: open the file and seek to the end.
                    725:                 */
                    726:                logfile = open(filename, OPEN_APPEND);
1.6     ! deraadt   727:                if (lseek(logfile, (off_t)0, SEEK_END) == BAD_LSEEK)
1.1       etheisen  728:                {
                    729:                        close(logfile);
                    730:                        logfile = -1;
                    731:                }
                    732:                break;
                    733:        case 'D': case 'd':
                    734:                /*
                    735:                 * Don't do anything.
                    736:                 */
1.4       millert   737:                free(filename);
1.1       etheisen  738:                return;
                    739:        case 'q':
                    740:                quit(QUIT_OK);
                    741:                /*NOTREACHED*/
                    742:        default:
                    743:                /*
                    744:                 * Eh?
                    745:                 */
                    746:                answer = query("Overwrite, Append, or Don't log? (Type \"O\", \"A\", \"D\" or \"q\") ", NULL_PARG);
                    747:                goto loop;
                    748:        }
                    749:
                    750:        if (logfile < 0)
                    751:        {
                    752:                /*
                    753:                 * Error in opening logfile.
                    754:                 */
                    755:                parg.p_string = filename;
                    756:                error("Cannot write to \"%s\"", &parg);
1.4       millert   757:                free(filename);
                    758:                return;
1.1       etheisen  759:        }
1.4       millert   760:        free(filename);
                    761:        SET_BINARY(logfile);
1.1       etheisen  762: }
                    763:
                    764: #endif