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

Annotation of src/usr.bin/less/lsystem.c, Revision 1.20

1.1       etheisen    1: /*
1.9       shadchin    2:  * Copyright (C) 1984-2012  Mark Nudelman
1.12      nicm        3:  * Modified for use with illumos by Garrett D'Amore.
                      4:  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
1.1       etheisen    5:  *
1.5       millert     6:  * You may distribute under the terms of either the GNU General Public
                      7:  * License or the Less License, as specified in the README file.
1.1       etheisen    8:  *
1.9       shadchin    9:  * For more information, see the README file.
1.10      nicm       10:  */
1.1       etheisen   11:
                     12: /*
                     13:  * Routines to execute other programs.
                     14:  * Necessarily very OS dependent.
                     15:  */
                     16:
1.18      mmcc       17: #include <signal.h>
                     18:
1.5       millert    19: #include "less.h"
1.1       etheisen   20: #include "position.h"
                     21:
                     22: extern int screen_trashed;
                     23: extern IFILE curr_ifile;
                     24:
1.10      nicm       25: static int pipe_data(char *cmd, off_t spos, off_t epos);
1.1       etheisen   26:
                     27: /*
                     28:  * Pass the specified command to a shell to be executed.
                     29:  * Like plain "system()", but handles resetting terminal modes, etc.
                     30:  */
1.10      nicm       31: void
                     32: lsystem(const char *cmd, const char *donemsg)
1.1       etheisen   33: {
1.10      nicm       34:        int inp;
                     35:        char *shell;
                     36:        char *p;
1.1       etheisen   37:        IFILE save_ifile;
                     38:
                     39:        /*
                     40:         * Print the command which is to be executed,
                     41:         * unless the command starts with a "-".
                     42:         */
                     43:        if (cmd[0] == '-')
                     44:                cmd++;
1.10      nicm       45:        else {
1.1       etheisen   46:                clear_bot();
                     47:                putstr("!");
                     48:                putstr(cmd);
                     49:                putstr("\n");
                     50:        }
                     51:
                     52:        /*
                     53:         * Close the current input file.
                     54:         */
1.5       millert    55:        save_ifile = save_curr_ifile();
1.16      deraadt    56:        (void) edit_ifile(NULL);
1.1       etheisen   57:
                     58:        /*
                     59:         * De-initialize the terminal and take out of raw mode.
                     60:         */
                     61:        deinit();
1.17      nicm       62:        flush(0);       /* Make sure the deinit chars get out */
1.1       etheisen   63:        raw_mode(0);
                     64:
                     65:        /*
                     66:         * Restore signals to their defaults.
                     67:         */
                     68:        init_signals(0);
                     69:
                     70:        /*
                     71:         * Force standard input to be the user's terminal
1.10      nicm       72:         * (the normal standard input), even if less's standard input
1.1       etheisen   73:         * is coming from a pipe.
                     74:         */
                     75:        inp = dup(0);
1.10      nicm       76:        (void) close(0);
1.19      deraadt    77:        if (open("/dev/tty", O_RDONLY) == -1)
1.10      nicm       78:                (void) dup(inp);
1.1       etheisen   79:
                     80:        /*
                     81:         * Pass the command to the system to be executed.
                     82:         * If we have a SHELL environment variable, use
                     83:         * <$SHELL -c "command"> instead of just <command>.
                     84:         * If the command is empty, just invoke a shell.
                     85:         */
                     86:        p = NULL;
1.10      nicm       87:        if ((shell = lgetenv("SHELL")) != NULL && *shell != '\0') {
                     88:                if (*cmd == '\0') {
1.13      tedu       89:                        p = estrdup(shell);
1.10      nicm       90:                } else {
1.5       millert    91:                        char *esccmd = shell_quote(cmd);
1.10      nicm       92:                        if (esccmd != NULL) {
                     93:                                p = easprintf("%s -c %s", shell, esccmd);
1.5       millert    94:                                free(esccmd);
                     95:                        }
1.1       etheisen   96:                }
                     97:        }
1.10      nicm       98:        if (p == NULL) {
1.1       etheisen   99:                if (*cmd == '\0')
1.13      tedu      100:                        p = estrdup("sh");
1.1       etheisen  101:                else
1.13      tedu      102:                        p = estrdup(cmd);
1.1       etheisen  103:        }
1.10      nicm      104:        (void) system(p);
1.1       etheisen  105:        free(p);
                    106:
                    107:        /*
                    108:         * Restore standard input, reset signals, raw mode, etc.
                    109:         */
1.10      nicm      110:        (void) close(0);
                    111:        (void) dup(inp);
                    112:        (void) close(inp);
                    113:
1.1       etheisen  114:        init_signals(1);
                    115:        raw_mode(1);
1.10      nicm      116:        if (donemsg != NULL) {
1.5       millert   117:                putstr(donemsg);
                    118:                putstr("  (press RETURN)");
                    119:                get_return();
1.10      nicm      120:                (void) putchr('\n');
1.17      nicm      121:                flush(0);
1.5       millert   122:        }
1.1       etheisen  123:        init();
                    124:        screen_trashed = 1;
                    125:
                    126:        /*
                    127:         * Reopen the current input file.
                    128:         */
1.5       millert   129:        reedit_ifile(save_ifile);
1.1       etheisen  130:
                    131:        /*
                    132:         * Since we were ignoring window change signals while we executed
                    133:         * the system command, we must assume the window changed.
1.20    ! schwarze  134:         * Warning: this leaves a signal pending (in "signal_winch"),
1.1       etheisen  135:         * so psignals() should be called soon after lsystem().
                    136:         */
1.10      nicm      137:        sigwinch(0);
1.1       etheisen  138: }
                    139:
                    140: /*
                    141:  * Pipe a section of the input file into the given shell command.
                    142:  * The section to be piped is the section "between" the current
                    143:  * position and the position marked by the given letter.
                    144:  *
1.5       millert   145:  * If the mark is after the current screen, the section between
                    146:  * the top line displayed and the mark is piped.
                    147:  * If the mark is before the current screen, the section between
                    148:  * the mark and the bottom line displayed is piped.
                    149:  * If the mark is on the current screen, or if the mark is ".",
                    150:  * the whole current screen is piped.
1.1       etheisen  151:  */
1.10      nicm      152: int
                    153: pipe_mark(int c, char *cmd)
1.1       etheisen  154: {
1.10      nicm      155:        off_t mpos, tpos, bpos;
1.1       etheisen  156:
                    157:        /*
                    158:         * mpos = the marked position.
                    159:         * tpos = top of screen.
                    160:         * bpos = bottom of screen.
                    161:         */
                    162:        mpos = markpos(c);
1.10      nicm      163:        if (mpos == -1)
1.1       etheisen  164:                return (-1);
                    165:        tpos = position(TOP);
1.10      nicm      166:        if (tpos == -1)
1.1       etheisen  167:                tpos = ch_zero();
                    168:        bpos = position(BOTTOM);
                    169:
1.10      nicm      170:        if (c == '.')
                    171:                return (pipe_data(cmd, tpos, bpos));
                    172:        else if (mpos <= tpos)
                    173:                return (pipe_data(cmd, mpos, bpos));
                    174:        else if (bpos == -1)
                    175:                return (pipe_data(cmd, tpos, bpos));
                    176:        else
                    177:                return (pipe_data(cmd, tpos, mpos));
1.1       etheisen  178: }
                    179:
                    180: /*
                    181:  * Create a pipe to the given shell command.
                    182:  * Feed it the file contents between the positions spos and epos.
                    183:  */
1.10      nicm      184: static int
                    185: pipe_data(char *cmd, off_t spos, off_t epos)
1.1       etheisen  186: {
1.10      nicm      187:        FILE *f;
                    188:        int c;
1.1       etheisen  189:
                    190:        /*
                    191:         * This is structured much like lsystem().
                    192:         * Since we're running a shell program, we must be careful
                    193:         * to perform the necessary deinitialization before running
                    194:         * the command, and reinitialization after it.
                    195:         */
1.10      nicm      196:        if (ch_seek(spos) != 0) {
1.15      deraadt   197:                error("Cannot seek to start position", NULL);
1.1       etheisen  198:                return (-1);
                    199:        }
                    200:
1.10      nicm      201:        if ((f = popen(cmd, "w")) == NULL) {
1.15      deraadt   202:                error("Cannot create pipe", NULL);
1.1       etheisen  203:                return (-1);
                    204:        }
                    205:        clear_bot();
                    206:        putstr("!");
                    207:        putstr(cmd);
                    208:        putstr("\n");
                    209:
                    210:        deinit();
1.17      nicm      211:        flush(0);
1.1       etheisen  212:        raw_mode(0);
                    213:        init_signals(0);
1.11      nicm      214:        lsignal(SIGPIPE, SIG_IGN);
1.1       etheisen  215:
                    216:        c = EOI;
1.10      nicm      217:        while (epos == -1 || spos++ <= epos) {
1.1       etheisen  218:                /*
                    219:                 * Read a character from the file and give it to the pipe.
                    220:                 */
                    221:                c = ch_forw_get();
                    222:                if (c == EOI)
                    223:                        break;
                    224:                if (putc(c, f) == EOF)
                    225:                        break;
                    226:        }
                    227:
                    228:        /*
                    229:         * Finish up the last line.
                    230:         */
1.10      nicm      231:        while (c != '\n' && c != EOI) {
                    232:                c = ch_forw_get();
                    233:                if (c == EOI)
                    234:                        break;
                    235:                if (putc(c, f) == EOF)
                    236:                        break;
                    237:        }
1.1       etheisen  238:
1.10      nicm      239:        (void) pclose(f);
1.1       etheisen  240:
1.11      nicm      241:        lsignal(SIGPIPE, SIG_DFL);
1.1       etheisen  242:        init_signals(1);
                    243:        raw_mode(1);
                    244:        init();
                    245:        screen_trashed = 1;
                    246:        /* {{ Probably don't need this here. }} */
1.10      nicm      247:        sigwinch(0);
1.1       etheisen  248:        return (0);
                    249: }