[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.7

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