2 * Copyright (C) 1984-2012 Mark Nudelman
3 * Modified for use with illumos by Garrett D'Amore.
4 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
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.
9 * For more information, see the README file.
13 * Routines to execute other programs.
14 * Necessarily very OS dependent.
22 extern int screen_trashed
;
23 extern IFILE curr_ifile
;
25 static int pipe_data(char *cmd
, off_t spos
, off_t epos
);
28 * Pass the specified command to a shell to be executed.
29 * Like plain "system()", but handles resetting terminal modes, etc.
32 lsystem(const char *cmd
, const char *donemsg
)
40 * Print the command which is to be executed,
41 * unless the command starts with a "-".
53 * Close the current input file.
55 save_ifile
= save_curr_ifile();
56 (void) edit_ifile(NULL
);
59 * De-initialize the terminal and take out of raw mode.
62 flush(0); /* Make sure the deinit chars get out */
66 * Restore signals to their defaults.
71 * Force standard input to be the user's terminal
72 * (the normal standard input), even if less's standard input
73 * is coming from a pipe.
77 if (open("/dev/tty", O_RDONLY
) < 0)
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.
87 if ((shell
= lgetenv("SHELL")) != NULL
&& *shell
!= '\0') {
91 char *esccmd
= shell_quote(cmd
);
93 p
= easprintf("%s -c %s", shell
, esccmd
);
108 * Restore standard input, reset signals, raw mode, etc.
116 if (donemsg
!= NULL
) {
118 putstr(" (press RETURN)");
127 * Reopen the current input file.
129 reedit_ifile(save_ifile
);
132 * Since we were ignoring window change signals while we executed
133 * the system command, we must assume the window changed.
134 * Warning: this leaves a signal pending (in "sigs"),
135 * so psignals() should be called soon after lsystem().
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.
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.
153 pipe_mark(int c
, char *cmd
)
155 off_t mpos
, tpos
, bpos
;
158 * mpos = the marked position.
159 * tpos = top of screen.
160 * bpos = bottom of screen.
165 tpos
= position(TOP
);
168 bpos
= position(BOTTOM
);
171 return (pipe_data(cmd
, tpos
, bpos
));
172 else if (mpos
<= tpos
)
173 return (pipe_data(cmd
, mpos
, bpos
));
175 return (pipe_data(cmd
, tpos
, bpos
));
177 return (pipe_data(cmd
, tpos
, mpos
));
181 * Create a pipe to the given shell command.
182 * Feed it the file contents between the positions spos and epos.
185 pipe_data(char *cmd
, off_t spos
, off_t epos
)
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.
196 if (ch_seek(spos
) != 0) {
197 error("Cannot seek to start position", NULL
);
201 if ((f
= popen(cmd
, "w")) == NULL
) {
202 error("Cannot create pipe", NULL
);
214 lsignal(SIGPIPE
, SIG_IGN
);
217 while (epos
== -1 || spos
++ <= epos
) {
219 * Read a character from the file and give it to the pipe.
224 if (putc(c
, f
) == EOF
)
229 * Finish up the last line.
231 while (c
!= '\n' && c
!= EOI
) {
235 if (putc(c
, f
) == EOF
)
241 lsignal(SIGPIPE
, SIG_DFL
);
246 /* {{ Probably don't need this here. }} */