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

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