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

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