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

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