Annotation of src/usr.bin/less/lsystem.c, Revision 1.1.1.1
1.1 etheisen 1: /*
2: * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice in the documentation and/or other materials provided with
12: * the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
15: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
20: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27:
28: /*
29: * Routines to execute other programs.
30: * Necessarily very OS dependent.
31: */
32:
33: #include <signal.h>
34: #include "less.h"
35: #include "position.h"
36:
37: #if MSOFTC
38: #include <dos.h>
39: #endif
40:
41: extern int screen_trashed;
42: extern IFILE curr_ifile;
43:
44:
45: #if HAVE_SYSTEM
46:
47: /*
48: * Pass the specified command to a shell to be executed.
49: * Like plain "system()", but handles resetting terminal modes, etc.
50: */
51: public void
52: lsystem(cmd)
53: char *cmd;
54: {
55: register int inp;
56: #if MSOFTC || OS2
57: register int inp2;
58: #endif
59: register char *shell;
60: register char *p;
61: IFILE save_ifile;
62:
63: /*
64: * Print the command which is to be executed,
65: * unless the command starts with a "-".
66: */
67: if (cmd[0] == '-')
68: cmd++;
69: else
70: {
71: clear_bot();
72: putstr("!");
73: putstr(cmd);
74: putstr("\n");
75: }
76:
77: /*
78: * Close the current input file.
79: */
80: save_ifile = curr_ifile;
81: (void) edit_ifile(NULL_IFILE);
82:
83: /*
84: * De-initialize the terminal and take out of raw mode.
85: */
86: deinit();
87: flush(); /* Make sure the deinit chars get out */
88: raw_mode(0);
89:
90: /*
91: * Restore signals to their defaults.
92: */
93: init_signals(0);
94:
95: /*
96: * Force standard input to be the user's terminal
97: * (the normal standard input), even if less's standard input
98: * is coming from a pipe.
99: */
100: inp = dup(0);
101: close(0);
102: if (OPEN_TTYIN() < 0)
103: dup(inp);
104:
105: /*
106: * Pass the command to the system to be executed.
107: * If we have a SHELL environment variable, use
108: * <$SHELL -c "command"> instead of just <command>.
109: * If the command is empty, just invoke a shell.
110: */
111: #if HAVE_SHELL
112: p = NULL;
113: if ((shell = getenv("SHELL")) != NULL && *shell != '\0')
114: {
115: if (*cmd == '\0')
116: p = save(shell);
117: else
118: {
119: p = (char *) ecalloc(strlen(shell) + strlen(cmd) + 7,
120: sizeof(char));
121: sprintf(p, "%s -c \"%s\"", shell, cmd);
122: }
123: }
124: if (p == NULL)
125: {
126: if (*cmd == '\0')
127: p = save("sh");
128: else
129: p = save(cmd);
130: }
131:
132: system(p);
133: free(p);
134: #else
135: #if OS2
136: if (*cmd == '\0')
137: cmd = "cmd.exe";
138: #endif
139: system(cmd);
140: #endif
141:
142: /*
143: * Restore standard input, reset signals, raw mode, etc.
144: */
145: close(0);
146: dup(inp);
147: close(inp);
148:
149: init_signals(1);
150: raw_mode(1);
151: init();
152: screen_trashed = 1;
153:
154: /*
155: * Reopen the current input file.
156: */
157: if (edit_ifile(save_ifile))
158: quit(QUIT_ERROR);
159:
160: #if defined(SIGWINCH) || defined(SIGWIND)
161: /*
162: * Since we were ignoring window change signals while we executed
163: * the system command, we must assume the window changed.
164: * Warning: this leaves a signal pending (in "sigs"),
165: * so psignals() should be called soon after lsystem().
166: */
167: winch(0);
168: #endif
169: }
170:
171: #endif
172:
173: #if PIPEC
174:
175: /*
176: * Pipe a section of the input file into the given shell command.
177: * The section to be piped is the section "between" the current
178: * position and the position marked by the given letter.
179: *
180: * The "current" position means the top line displayed if the mark
181: * is after the current screen, or the bottom line displayed if
182: * the mark is before the current screen.
183: * If the mark is on the current screen, the whole screen is displayed.
184: */
185: public int
186: pipe_mark(c, cmd)
187: int c;
188: char *cmd;
189: {
190: POSITION mpos, tpos, bpos;
191:
192: /*
193: * mpos = the marked position.
194: * tpos = top of screen.
195: * bpos = bottom of screen.
196: */
197: mpos = markpos(c);
198: if (mpos == NULL_POSITION)
199: return (-1);
200: tpos = position(TOP);
201: if (tpos == NULL_POSITION)
202: tpos = ch_zero();
203: bpos = position(BOTTOM);
204:
205: if (c == '.')
206: return (pipe_data(cmd, tpos, bpos));
207: else if (mpos <= tpos)
208: return (pipe_data(cmd, mpos, tpos));
209: else if (bpos == NULL_POSITION)
210: return (pipe_data(cmd, tpos, bpos));
211: else
212: return (pipe_data(cmd, tpos, mpos));
213: }
214:
215: /*
216: * Create a pipe to the given shell command.
217: * Feed it the file contents between the positions spos and epos.
218: */
219: public int
220: pipe_data(cmd, spos, epos)
221: char *cmd;
222: POSITION spos;
223: POSITION epos;
224: {
225: register FILE *f;
226: register int c;
227: extern FILE *popen();
228:
229: /*
230: * This is structured much like lsystem().
231: * Since we're running a shell program, we must be careful
232: * to perform the necessary deinitialization before running
233: * the command, and reinitialization after it.
234: */
235: if (ch_seek(spos) != 0)
236: {
237: error("Cannot seek to start position", NULL_PARG);
238: return (-1);
239: }
240:
241: if ((f = popen(cmd, "w")) == NULL)
242: {
243: error("Cannot create pipe", NULL_PARG);
244: return (-1);
245: }
246: clear_bot();
247: putstr("!");
248: putstr(cmd);
249: putstr("\n");
250:
251: deinit();
252: flush();
253: raw_mode(0);
254: init_signals(0);
255: #ifdef SIGPIPE
256: SIGNAL(SIGPIPE, SIG_IGN);
257: #endif
258:
259: c = EOI;
260: while (epos == NULL_POSITION || spos++ <= epos)
261: {
262: /*
263: * Read a character from the file and give it to the pipe.
264: */
265: c = ch_forw_get();
266: if (c == EOI)
267: break;
268: if (putc(c, f) == EOF)
269: break;
270: }
271:
272: /*
273: * Finish up the last line.
274: */
275: while (c != '\n' && c != EOI )
276: {
277: c = ch_forw_get();
278: if (c == EOI)
279: break;
280: if (putc(c, f) == EOF)
281: break;
282: }
283:
284: pclose(f);
285:
286: #ifdef SIGPIPE
287: SIGNAL(SIGPIPE, SIG_DFL);
288: #endif
289: init_signals(1);
290: raw_mode(1);
291: init();
292: screen_trashed = 1;
293: #if defined(SIGWINCH) || defined(SIGWIND)
294: /* {{ Probably don't need this here. }} */
295: winch(0);
296: #endif
297: return (0);
298: }
299:
300: #endif