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

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