summaryrefslogtreecommitdiff
path: root/usr.bin/less/lsystem.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/less/lsystem.c')
-rw-r--r--usr.bin/less/lsystem.c300
1 files changed, 300 insertions, 0 deletions
diff --git a/usr.bin/less/lsystem.c b/usr.bin/less/lsystem.c
new file mode 100644
index 00000000000..db0e4fca2fd
--- /dev/null
+++ b/usr.bin/less/lsystem.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice in the documentation and/or other materials provided with
+ * the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ * Routines to execute other programs.
+ * Necessarily very OS dependent.
+ */
+
+#include <signal.h>
+#include "less.h"
+#include "position.h"
+
+#if MSOFTC
+#include <dos.h>
+#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)
+ char *cmd;
+{
+ register int inp;
+#if MSOFTC || OS2
+ register int inp2;
+#endif
+ register char *shell;
+ register char *p;
+ IFILE save_ifile;
+
+ /*
+ * 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");
+ }
+
+ /*
+ * Close the current input file.
+ */
+ save_ifile = 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);
+
+ /*
+ * Restore signals to their defaults.
+ */
+ init_signals(0);
+
+ /*
+ * 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 (OPEN_TTYIN() < 0)
+ dup(inp);
+
+ /*
+ * 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 = getenv("SHELL")) != NULL && *shell != '\0')
+ {
+ if (*cmd == '\0')
+ p = save(shell);
+ else
+ {
+ p = (char *) ecalloc(strlen(shell) + strlen(cmd) + 7,
+ sizeof(char));
+ sprintf(p, "%s -c \"%s\"", shell, cmd);
+ }
+ }
+ if (p == NULL)
+ {
+ if (*cmd == '\0')
+ p = save("sh");
+ else
+ p = save(cmd);
+ }
+
+ system(p);
+ free(p);
+#else
+#if OS2
+ if (*cmd == '\0')
+ cmd = "cmd.exe";
+#endif
+ system(cmd);
+#endif
+
+ /*
+ * Restore standard input, reset signals, raw mode, etc.
+ */
+ close(0);
+ dup(inp);
+ close(inp);
+
+ init_signals(1);
+ raw_mode(1);
+ init();
+ screen_trashed = 1;
+
+ /*
+ * Reopen the current input file.
+ */
+ if (edit_ifile(save_ifile))
+ quit(QUIT_ERROR);
+
+#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.
+ *
+ * The "current" position means the top line displayed if the mark
+ * is after the current screen, or the bottom line displayed if
+ * the mark is before the current screen.
+ * If the mark is on the current screen, the whole screen is displayed.
+ */
+ 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, tpos));
+ 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);
+#ifdef SIGPIPE
+ SIGNAL(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
+ SIGNAL(SIGPIPE, SIG_DFL);
+#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