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