2
* Copyright (C) 1984-2000 Mark Nudelman
4
* You may distribute under the terms of either the GNU General Public
5
* License or the Less License, as specified in the README file.
7
* For more information about less, or for information on how to
8
* contact the author, see the README file.
13
* Routines to execute other programs.
14
* Necessarily very OS dependent.
25
#define setdisk(n) _chdrive((n)+1)
31
extern int screen_trashed;
32
extern IFILE curr_ifile;
38
* Pass the specified command to a shell to be executed.
39
* Like plain "system()", but handles resetting terminal modes, etc.
53
char cwd[FILENAME_MAX+1];
57
* Print the command which is to be executed,
58
* unless the command starts with a "-".
72
* Working directory is global on MSDOS.
73
* The child might change the working directory, so we
74
* must save and restore CWD across calls to "system",
75
* or else we won't find our file when we return and
76
* try to "reedit_ifile" it.
78
getcwd(cwd, FILENAME_MAX);
82
* Close the current input file.
84
save_ifile = save_curr_ifile();
85
(void) edit_ifile(NULL_IFILE);
88
* De-initialize the terminal and take out of raw mode.
91
flush(); /* Make sure the deinit chars get out */
93
#if MSDOS_COMPILER==WIN32C
98
* Restore signals to their defaults.
104
* Force standard input to be the user's terminal
105
* (the normal standard input), even if less's standard input
106
* is coming from a pipe.
111
/* The __open() system call translates "/dev/tty" to "con". */
112
if (__open("/dev/tty", OPEN_READ) < 0)
114
if (open("/dev/tty", OPEN_READ) < 0)
120
* Pass the command to the system to be executed.
121
* If we have a SHELL environment variable, use
122
* <$SHELL -c "command"> instead of just <command>.
123
* If the command is empty, just invoke a shell.
127
if ((shell = lgetenv("SHELL")) != NULL && *shell != '\0')
133
char *esccmd = shell_quote(cmd);
136
p = (char *) ecalloc(strlen(shell) +
137
strlen(esccmd) + 5, sizeof(char));
138
sprintf(p, "%s %s %s", shell, shell_coption(), esccmd);
153
#if MSDOS_COMPILER==DJGPPC
155
* Make stdin of the child be in cooked mode.
159
* We don't need to catch signals of the child (it
160
* also makes trouble with some DPMI servers).
162
__djgpp_exception_toggle();
164
__djgpp_exception_toggle();
172
* Restore standard input, reset signals, raw mode, etc.
179
#if MSDOS_COMPILER==WIN32C
187
putstr(" (press RETURN)");
197
* Restore the previous directory (possibly
198
* changed by the child program we just ran).
201
#if MSDOS_COMPILER != DJGPPC
203
* Some versions of chdir() don't change to the drive
204
* which is part of CWD. (DJGPP does this in chdir.)
208
if (cwd[0] >= 'a' && cwd[0] <= 'z')
209
setdisk(cwd[0] - 'a');
210
else if (cwd[0] >= 'A' && cwd[0] <= 'Z')
211
setdisk(cwd[0] - 'A');
217
* Reopen the current input file.
219
reedit_ifile(save_ifile);
221
#if defined(SIGWINCH) || defined(SIGWIND)
223
* Since we were ignoring window change signals while we executed
224
* the system command, we must assume the window changed.
225
* Warning: this leaves a signal pending (in "sigs"),
226
* so psignals() should be called soon after lsystem().
237
* Pipe a section of the input file into the given shell command.
238
* The section to be piped is the section "between" the current
239
* position and the position marked by the given letter.
241
* If the mark is after the current screen, the section between
242
* the top line displayed and the mark is piped.
243
* If the mark is before the current screen, the section between
244
* the mark and the bottom line displayed is piped.
245
* If the mark is on the current screen, or if the mark is ".",
246
* the whole current screen is piped.
253
POSITION mpos, tpos, bpos;
256
* mpos = the marked position.
257
* tpos = top of screen.
258
* bpos = bottom of screen.
261
if (mpos == NULL_POSITION)
263
tpos = position(TOP);
264
if (tpos == NULL_POSITION)
266
bpos = position(BOTTOM);
269
return (pipe_data(cmd, tpos, bpos));
270
else if (mpos <= tpos)
271
return (pipe_data(cmd, mpos, bpos));
272
else if (bpos == NULL_POSITION)
273
return (pipe_data(cmd, tpos, bpos));
275
return (pipe_data(cmd, tpos, mpos));
279
* Create a pipe to the given shell command.
280
* Feed it the file contents between the positions spos and epos.
283
pipe_data(cmd, spos, epos)
290
extern FILE *popen();
293
* This is structured much like lsystem().
294
* Since we're running a shell program, we must be careful
295
* to perform the necessary deinitialization before running
296
* the command, and reinitialization after it.
298
if (ch_seek(spos) != 0)
300
error("Cannot seek to start position", NULL_PARG);
304
if ((f = popen(cmd, "w")) == NULL)
306
error("Cannot create pipe", NULL_PARG);
318
#if MSDOS_COMPILER==WIN32C
322
LSIGNAL(SIGPIPE, SIG_IGN);
326
while (epos == NULL_POSITION || spos++ <= epos)
329
* Read a character from the file and give it to the pipe.
334
if (putc(c, f) == EOF)
339
* Finish up the last line.
341
while (c != '\n' && c != EOI )
346
if (putc(c, f) == EOF)
353
LSIGNAL(SIGPIPE, SIG_DFL);
355
#if MSDOS_COMPILER==WIN32C
362
#if defined(SIGWINCH) || defined(SIGWIND)
363
/* {{ Probably don't need this here. }} */
373
* Popen, and Pclose, for OS-9.
375
* Based on code copyright (c) 1988 by Wolfgang Ocker, Puchheim,
376
* Ulli Dessauer, Germering and
377
* Reimer Mellin, Muenchen
380
* These functions can be copied and distributed freely for any
381
* non-commercial purposes. It can only be incorporated into
382
* commercial software with the written permission of the authors.
384
* TOP-specific code stripped out and adapted for less by M.Gregorie, 1996
386
* address: Wolfgang Ocker
387
* Lochhauserstrasse 35a
391
* e-mail: weo@altger.UUCP, ud@altger.UUCP, ram@altger.UUCP
392
* pyramid!tmpmbx!recco!weo
393
* pyramid!tmpmbx!nitmar!ud
394
* pyramid!tmpmbx!ramsys!ram
402
* gregorie@logica.com
406
extern char **environ;
407
extern char *getenv();
408
extern int os9forkc();
409
static int pids[_NFILE] = { 0, 0, 0, 0, 0, 0, 0, 0,
410
0, 0, 0, 0, 0, 0, 0, 0,
411
0, 0, 0, 0, 0, 0, 0, 0,
412
0, 0, 0, 0, 0, 0, 0, 0 };
416
FILE *popen(name, mode)
420
int fd, fd2, fdsav, pid;
421
static char *argv[] = {NULL, NULL, NULL };
422
static char cmd[200];
423
static char cmd_path[200];
427
if ((shell = getenv("SHELL")) == NULL)
432
strcpy(cmd_path, cp);
433
if (cp = index(cmd_path, ' '))
436
strcat(cmd, cmd_path);
445
mode is "r" (stdout) or "w" (stdin)
453
default: return(NULL);
460
creat("/pipe", S_IWRITE+S_IREAD);
461
pid = os9exec(os9forkc, argv[0], argv, environ, 0, 0, 3);
469
r = fdopen(fd2, mode);
494
while ((pid = wait(&status)) != -1)
498
for (i = 0; i < _NFILE; i++)