summaryrefslogtreecommitdiff
path: root/lsystem.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2012-07-21 20:40:00 +0000
committerLorry <lorry@roadtrain.codethink.co.uk>2012-09-24 16:52:48 +0000
commit09a405d8f652b56944c93ebf5c673cdfe5319b04 (patch)
tree9cc4518b0a21096735b20ac3204a6fa032f1c566 /lsystem.c
downloadless-09a405d8f652b56944c93ebf5c673cdfe5319b04.tar.gz
Imported from /srv/lorry/lorry-area/less/less-451.tar.gz.HEADless-451masterbaserock/morph
Diffstat (limited to 'lsystem.c')
-rwxr-xr-xlsystem.c373
1 files changed, 373 insertions, 0 deletions
diff --git a/lsystem.c b/lsystem.c
new file mode 100755
index 0000000..674e5a2
--- /dev/null
+++ b/lsystem.c
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 1984-2012 Mark Nudelman
+ *
+ * You may distribute under the terms of either the GNU General Public
+ * License or the Less License, as specified in the README file.
+ *
+ * For more information, see the README file.
+ */
+
+
+/*
+ * Routines to execute other programs.
+ * Necessarily very OS dependent.
+ */
+
+#include "less.h"
+#include <signal.h>
+#include "position.h"
+
+#if MSDOS_COMPILER
+#include <dos.h>
+#ifdef _MSC_VER
+#include <direct.h>
+#define setdisk(n) _chdrive((n)+1)
+#else
+#include <dir.h>
+#endif
+#endif
+
+extern int screen_trashed;
+extern IFILE curr_ifile;
+
+
+#if HAVE_SYSTEM
+
+/*
+ * Pass the specified command to a shell to be executed.
+ * Like plain "system()", but handles resetting terminal modes, etc.
+ */
+ public void
+lsystem(cmd, donemsg)
+ char *cmd;
+ char *donemsg;
+{
+ register int inp;
+#if HAVE_SHELL
+ register char *shell;
+ register char *p;
+#endif
+ IFILE save_ifile;
+#if MSDOS_COMPILER && MSDOS_COMPILER!=WIN32C
+ char cwd[FILENAME_MAX+1];
+#endif
+
+ /*
+ * Print the command which is to be executed,
+ * unless the command starts with a "-".
+ */
+ if (cmd[0] == '-')
+ cmd++;
+ else
+ {
+ clear_bot();
+ putstr("!");
+ putstr(cmd);
+ putstr("\n");
+ }
+
+#if MSDOS_COMPILER
+#if MSDOS_COMPILER==WIN32C
+ if (*cmd == '\0')
+ cmd = getenv("COMSPEC");
+#else
+ /*
+ * Working directory is global on MSDOS.
+ * The child might change the working directory, so we
+ * must save and restore CWD across calls to "system",
+ * or else we won't find our file when we return and
+ * try to "reedit_ifile" it.
+ */
+ getcwd(cwd, FILENAME_MAX);
+#endif
+#endif
+
+ /*
+ * Close the current input file.
+ */
+ save_ifile = save_curr_ifile();
+ (void) edit_ifile(NULL_IFILE);
+
+ /*
+ * De-initialize the terminal and take out of raw mode.
+ */
+ deinit();
+ flush(); /* Make sure the deinit chars get out */
+ raw_mode(0);
+#if MSDOS_COMPILER==WIN32C
+ close_getchr();
+#endif
+
+ /*
+ * Restore signals to their defaults.
+ */
+ init_signals(0);
+
+#if HAVE_DUP
+ /*
+ * Force standard input to be the user's terminal
+ * (the normal standard input), even if less's standard input
+ * is coming from a pipe.
+ */
+ inp = dup(0);
+ close(0);
+#if OS2
+ /* The __open() system call translates "/dev/tty" to "con". */
+ if (__open("/dev/tty", OPEN_READ) < 0)
+#else
+ if (open("/dev/tty", OPEN_READ) < 0)
+#endif
+ dup(inp);
+#endif
+
+ /*
+ * Pass the command to the system to be executed.
+ * If we have a SHELL environment variable, use
+ * <$SHELL -c "command"> instead of just <command>.
+ * If the command is empty, just invoke a shell.
+ */
+#if HAVE_SHELL
+ p = NULL;
+ if ((shell = lgetenv("SHELL")) != NULL && *shell != '\0')
+ {
+ if (*cmd == '\0')
+ p = save(shell);
+ else
+ {
+ char *esccmd = shell_quote(cmd);
+ if (esccmd != NULL)
+ {
+ int len = strlen(shell) + strlen(esccmd) + 5;
+ p = (char *) ecalloc(len, sizeof(char));
+ SNPRINTF3(p, len, "%s %s %s", shell, shell_coption(), esccmd);
+ free(esccmd);
+ }
+ }
+ }
+ if (p == NULL)
+ {
+ if (*cmd == '\0')
+ p = save("sh");
+ else
+ p = save(cmd);
+ }
+ system(p);
+ free(p);
+#else
+#if MSDOS_COMPILER==DJGPPC
+ /*
+ * Make stdin of the child be in cooked mode.
+ */
+ setmode(0, O_TEXT);
+ /*
+ * We don't need to catch signals of the child (it
+ * also makes trouble with some DPMI servers).
+ */
+ __djgpp_exception_toggle();
+ system(cmd);
+ __djgpp_exception_toggle();
+#else
+ system(cmd);
+#endif
+#endif
+
+#if HAVE_DUP
+ /*
+ * Restore standard input, reset signals, raw mode, etc.
+ */
+ close(0);
+ dup(inp);
+ close(inp);
+#endif
+
+#if MSDOS_COMPILER==WIN32C
+ open_getchr();
+#endif
+ init_signals(1);
+ raw_mode(1);
+ if (donemsg != NULL)
+ {
+ putstr(donemsg);
+ putstr(" (press RETURN)");
+ get_return();
+ putchr('\n');
+ flush();
+ }
+ init();
+ screen_trashed = 1;
+
+#if MSDOS_COMPILER && MSDOS_COMPILER!=WIN32C
+ /*
+ * Restore the previous directory (possibly
+ * changed by the child program we just ran).
+ */
+ chdir(cwd);
+#if MSDOS_COMPILER != DJGPPC
+ /*
+ * Some versions of chdir() don't change to the drive
+ * which is part of CWD. (DJGPP does this in chdir.)
+ */
+ if (cwd[1] == ':')
+ {
+ if (cwd[0] >= 'a' && cwd[0] <= 'z')
+ setdisk(cwd[0] - 'a');
+ else if (cwd[0] >= 'A' && cwd[0] <= 'Z')
+ setdisk(cwd[0] - 'A');
+ }
+#endif
+#endif
+
+ /*
+ * Reopen the current input file.
+ */
+ reedit_ifile(save_ifile);
+
+#if defined(SIGWINCH) || defined(SIGWIND)
+ /*
+ * Since we were ignoring window change signals while we executed
+ * the system command, we must assume the window changed.
+ * Warning: this leaves a signal pending (in "sigs"),
+ * so psignals() should be called soon after lsystem().
+ */
+ winch(0);
+#endif
+}
+
+#endif
+
+#if PIPEC
+
+/*
+ * Pipe a section of the input file into the given shell command.
+ * The section to be piped is the section "between" the current
+ * position and the position marked by the given letter.
+ *
+ * If the mark is after the current screen, the section between
+ * the top line displayed and the mark is piped.
+ * If the mark is before the current screen, the section between
+ * the mark and the bottom line displayed is piped.
+ * If the mark is on the current screen, or if the mark is ".",
+ * the whole current screen is piped.
+ */
+ public int
+pipe_mark(c, cmd)
+ int c;
+ char *cmd;
+{
+ POSITION mpos, tpos, bpos;
+
+ /*
+ * mpos = the marked position.
+ * tpos = top of screen.
+ * bpos = bottom of screen.
+ */
+ mpos = markpos(c);
+ if (mpos == NULL_POSITION)
+ return (-1);
+ tpos = position(TOP);
+ if (tpos == NULL_POSITION)
+ tpos = ch_zero();
+ bpos = position(BOTTOM);
+
+ if (c == '.')
+ return (pipe_data(cmd, tpos, bpos));
+ else if (mpos <= tpos)
+ return (pipe_data(cmd, mpos, bpos));
+ else if (bpos == NULL_POSITION)
+ return (pipe_data(cmd, tpos, bpos));
+ else
+ return (pipe_data(cmd, tpos, mpos));
+}
+
+/*
+ * Create a pipe to the given shell command.
+ * Feed it the file contents between the positions spos and epos.
+ */
+ public int
+pipe_data(cmd, spos, epos)
+ char *cmd;
+ POSITION spos;
+ POSITION epos;
+{
+ register FILE *f;
+ register int c;
+ extern FILE *popen();
+
+ /*
+ * This is structured much like lsystem().
+ * Since we're running a shell program, we must be careful
+ * to perform the necessary deinitialization before running
+ * the command, and reinitialization after it.
+ */
+ if (ch_seek(spos) != 0)
+ {
+ error("Cannot seek to start position", NULL_PARG);
+ return (-1);
+ }
+
+ if ((f = popen(cmd, "w")) == NULL)
+ {
+ error("Cannot create pipe", NULL_PARG);
+ return (-1);
+ }
+ clear_bot();
+ putstr("!");
+ putstr(cmd);
+ putstr("\n");
+
+ deinit();
+ flush();
+ raw_mode(0);
+ init_signals(0);
+#if MSDOS_COMPILER==WIN32C
+ close_getchr();
+#endif
+#ifdef SIGPIPE
+ LSIGNAL(SIGPIPE, SIG_IGN);
+#endif
+
+ c = EOI;
+ while (epos == NULL_POSITION || spos++ <= epos)
+ {
+ /*
+ * Read a character from the file and give it to the pipe.
+ */
+ c = ch_forw_get();
+ if (c == EOI)
+ break;
+ if (putc(c, f) == EOF)
+ break;
+ }
+
+ /*
+ * Finish up the last line.
+ */
+ while (c != '\n' && c != EOI )
+ {
+ c = ch_forw_get();
+ if (c == EOI)
+ break;
+ if (putc(c, f) == EOF)
+ break;
+ }
+
+ pclose(f);
+
+#ifdef SIGPIPE
+ LSIGNAL(SIGPIPE, SIG_DFL);
+#endif
+#if MSDOS_COMPILER==WIN32C
+ open_getchr();
+#endif
+ init_signals(1);
+ raw_mode(1);
+ init();
+ screen_trashed = 1;
+#if defined(SIGWINCH) || defined(SIGWIND)
+ /* {{ Probably don't need this here. }} */
+ winch(0);
+#endif
+ return (0);
+}
+
+#endif