]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/miscellany/less-177/lsystem.c
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / docs / historical / mh-6.8.5 / miscellany / less-177 / lsystem.c
1 /*
2 * Routines to execute other programs.
3 * Necessarily very OS dependent.
4 */
5
6 #include <stdio.h>
7 #include <signal.h>
8
9 #include "less.h"
10 #include "position.h"
11
12 #if __MSDOS__
13 #include <process.h>
14 #include <dos.h>
15 #include <fcntl.h>
16 #include <io.h>
17 #include <errno.h>
18 #include <dir.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <time.h>
22 #include <ctype.h>
23 char get_swchar();
24 void swchar_to_dos();
25 void swchar_to_unix();
26 #endif
27
28 extern char *getenv();
29
30 extern int screen_trashed;
31 extern IFILE curr_ifile;
32
33
34 /*
35 * Pass the specified command to a shell to be executed.
36 * Like plain "system()", but handles resetting terminal modes, etc.
37 */
38 public void
39 lsystem(cmd)
40 char *cmd;
41 {
42 register int inp;
43 register char *shell;
44 register char *p;
45 register char *curr_filename;
46
47 /*
48 * Print the command which is to be executed,
49 * unless the command starts with a "-".
50 */
51 if (cmd[0] == '-')
52 cmd++;
53 else
54 {
55 lower_left();
56 clear_eol();
57 putstr("!");
58 putstr(cmd);
59 putstr("\n");
60 }
61
62 /*
63 * Close the current input file.
64 */
65 curr_filename = get_filename(curr_ifile);
66 (void) edit(NULL, 0);
67
68 /*
69 * De-initialize the terminal and take out of raw mode.
70 */
71 deinit();
72 flush(); /* Make sure the deinit chars get out */
73 raw_mode(0);
74
75 /*
76 * Restore signals to their defaults.
77 */
78 init_signals(0);
79
80 /*
81 * Force standard input to be the user's terminal
82 * (the normal standard input), even if less's standard input
83 * is coming from a pipe.
84 */
85 #if __MSDOS__
86 {
87 register int inp2;
88
89 inp = dup(0);
90 inp2 = open("CON", O_TEXT|O_RDONLY);
91 dup2(0,inp2);
92 }
93 #else
94 inp = dup(0);
95 close(0);
96 if (open("/dev/tty", 0) < 0)
97 dup(inp);
98 #endif
99
100 /*
101 * Pass the command to the system to be executed.
102 * If we have a SHELL environment variable, use
103 * <$SHELL -c "command"> instead of just <command>.
104 * If the command is empty, just invoke a shell.
105 */
106 #if __MSDOS__
107 {
108 int result;
109 char sw_char;
110
111 sw_char = get_swchar();
112 swchar_to_dos();
113 result = system(cmd);
114 if (result != 0)
115 perror("less");
116 if (sw_char == '-')
117 swchar_to_unix();
118 }
119 #else
120 p = NULL;
121 if ((shell = getenv("SHELL")) != NULL && *shell != '\0')
122 {
123 if (*cmd == '\0')
124 p = save(shell);
125 else
126 {
127 p = (char *) ecalloc(strlen(shell) + strlen(cmd) + 7,
128 sizeof(char));
129 sprintf(p, "%s -c \"%s\"", shell, cmd);
130 }
131 }
132 if (p == NULL)
133 {
134 if (*cmd == '\0')
135 p = save("sh");
136 else
137 p = save(cmd);
138 }
139
140 system(p);
141 free(p);
142 #endif
143
144 /*
145 * Restore standard input, reset signals, raw mode, etc.
146 */
147 #if __MSDOS__
148 close(inp2);
149 dup2(0,inp);
150 close(inp);
151 #else
152 close(0);
153 dup(inp);
154 close(inp);
155 #endif
156
157 init_signals(1);
158 raw_mode(1);
159 init();
160 screen_trashed = 1;
161
162 /*
163 * Reopen the current input file.
164 */
165 (void) edit(curr_filename, 0);
166
167 #if defined(SIGWINCH) || defined(SIGWIND)
168 /*
169 * Since we were ignoring window change signals while we executed
170 * the system command, we must assume the window changed.
171 * Warning: this leaves a signal pending (in "sigs"),
172 * so psignals() should be called soon after lsystem().
173 */
174 winch();
175 #endif
176 }
177
178 #if PIPEC
179
180 /*
181 * Pipe a section of the input file into the given shell command.
182 * The section to be piped is the section "between" the current
183 * position and the position marked by the given letter.
184 *
185 * The "current" position means the top line displayed if the mark
186 * is after the current screen, or the bottom line displayed if
187 * the mark is before the current screen.
188 * If the mark is on the current screen, the whole screen is displayed.
189 */
190 public int
191 pipe_mark(c, cmd)
192 int c;
193 char *cmd;
194 {
195 POSITION mpos, tpos, bpos;
196
197 /*
198 * mpos = the marked position.
199 * tpos = top of screen.
200 * bpos = bottom of screen.
201 */
202 mpos = markpos(c);
203 if (mpos == NULL_POSITION)
204 return (-1);
205 tpos = position(TOP);
206 if (tpos == NULL_POSITION)
207 tpos = ch_zero();
208 bpos = position(BOTTOM);
209
210 if (c == '.')
211 return (pipe_data(cmd, tpos, bpos));
212 else if (mpos <= tpos)
213 return (pipe_data(cmd, mpos, tpos));
214 else if (bpos == NULL_POSITION)
215 return (pipe_data(cmd, tpos, bpos));
216 else
217 return (pipe_data(cmd, tpos, mpos));
218 }
219
220 /*
221 * Create a pipe to the given shell command.
222 * Feed it the file contents between the positions spos and epos.
223 */
224 public int
225 pipe_data(cmd, spos, epos)
226 char *cmd;
227 POSITION spos;
228 POSITION epos;
229 {
230 register FILE *f;
231 register int c;
232 extern FILE *popen();
233
234 /*
235 * This is structured much like lsystem().
236 * Since we're running a shell program, we must be careful
237 * to perform the necessary deinitialization before running
238 * the command, and reinitialization after it.
239 */
240 if (ch_seek(spos) != 0)
241 {
242 error("Cannot seek to start position", NULL_PARG);
243 return (-1);
244 }
245
246 if ((f = popen(cmd, "w")) == NULL)
247 {
248 error("Cannot create pipe", NULL_PARG);
249 return (-1);
250 }
251 lower_left();
252 clear_eol();
253 putstr("!");
254 putstr(cmd);
255 putstr("\n");
256
257 deinit();
258 flush();
259 raw_mode(0);
260 init_signals(0);
261 #ifdef SIGPIPE
262 SIGNAL(SIGPIPE, SIG_IGN);
263 #endif
264
265 while (epos == NULL_POSITION || spos++ <= epos)
266 {
267 /*
268 * Read a character from the file and give it to the pipe.
269 */
270 c = ch_forw_get();
271 if (c == EOI)
272 break;
273 if (putc(c, f) == EOF)
274 break;
275 }
276
277 /*
278 * Finish up the last line.
279 */
280 while (c != '\n' && c != EOI )
281 {
282 c = ch_forw_get();
283 if (c == EOI)
284 break;
285 if (putc(c, f) == EOF)
286 break;
287 }
288
289 pclose(f);
290
291 #ifdef SIGPIPE
292 SIGNAL(SIGPIPE, SIG_DFL);
293 #endif
294 init_signals(1);
295 raw_mode(1);
296 init();
297 screen_trashed = 1;
298 #if defined(SIGWINCH) || defined(SIGWIND)
299 /* {{ Probably don't need this here. }} */
300 winch();
301 #endif
302 return (0);
303 }
304
305 #endif