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

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