summaryrefslogtreecommitdiffstats
path: root/contrib/less/lsystem.c
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2000-05-22 09:53:22 +0000
committerps <ps@FreeBSD.org>2000-05-22 09:53:22 +0000
commit1b28029810e9c377087ea5a45acc8767cf0196b3 (patch)
tree27b16fc210b9a302c9e74f90e36a9b5ed21e6300 /contrib/less/lsystem.c
downloadFreeBSD-src-1b28029810e9c377087ea5a45acc8767cf0196b3.zip
FreeBSD-src-1b28029810e9c377087ea5a45acc8767cf0196b3.tar.gz
Import the [now] dual licensed version 3.5.4 of less. It is
distributed under your choice of the GPL or a BSD style license. Reviewed by: peter Obtained from: http://home.flash.net/~marknu/less/
Diffstat (limited to 'contrib/less/lsystem.c')
-rw-r--r--contrib/less/lsystem.c510
1 files changed, 510 insertions, 0 deletions
diff --git a/contrib/less/lsystem.c b/contrib/less/lsystem.c
new file mode 100644
index 0000000..92286a3
--- /dev/null
+++ b/contrib/less/lsystem.c
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C) 1984-2000 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 about less, or for information on how to
+ * contact the author, see the README file.
+ */
+
+
+/*
+ * Routines to execute other programs.
+ * Necessarily very OS dependent.
+ */
+
+#include <signal.h>
+#include "less.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
+ 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
+ /*
+ * 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
+
+ /*
+ * 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 (open("/dev/tty", OPEN_READ) < 0)
+ 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;
+ if ((esccmd = esc_metachars(cmd)) == NULL)
+ {
+ p = (char *) ecalloc(strlen(shell) +
+ strlen(cmd) + 7, sizeof(char));
+ sprintf(p, "%s -c \"%s\"", shell, cmd);
+ } else
+ {
+ p = (char *) ecalloc(strlen(shell) +
+ strlen(esccmd) + 5, sizeof(char));
+ sprintf(p, "%s -c %s", shell, 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
+ /*
+ * 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
+
+#ifdef _OSK
+/*
+ * Popen, and Pclose, for OS-9.
+ *
+ * Based on code copyright (c) 1988 by Wolfgang Ocker, Puchheim,
+ * Ulli Dessauer, Germering and
+ * Reimer Mellin, Muenchen
+ * (W-Germany)
+ *
+ * These functions can be copied and distributed freely for any
+ * non-commercial purposes. It can only be incorporated into
+ * commercial software with the written permission of the authors.
+ *
+ * TOP-specific code stripped out and adapted for less by M.Gregorie, 1996
+ *
+ * address: Wolfgang Ocker
+ * Lochhauserstrasse 35a
+ * D-8039 Puchheim
+ * West Germany
+ *
+ * e-mail: weo@altger.UUCP, ud@altger.UUCP, ram@altger.UUCP
+ * pyramid!tmpmbx!recco!weo
+ * pyramid!tmpmbx!nitmar!ud
+ * pyramid!tmpmbx!ramsys!ram
+ *
+ * Martin Gregorie
+ * 10 Sadlers Mead
+ * Harlow
+ * Essex, CM18 6HG
+ * U.K.
+ *
+ * gregorie@logica.com
+ */
+#include <strings.h>
+#include <errno.h>
+extern char **environ;
+extern char *getenv();
+extern int os9forkc();
+static int pids[_NFILE] = { 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 };
+/*
+ * p o p e n
+ */
+FILE *popen(name, mode)
+ char *name;
+ char *mode;
+{
+ int fd, fd2, fdsav, pid;
+ static char *argv[] = {NULL, NULL, NULL };
+ static char cmd[200];
+ static char cmd_path[200];
+ char *cp;
+ char *shell;
+ FILE *r;
+ if ((shell = getenv("SHELL")) == NULL)
+ return(NULL);
+ cp = name;
+ while (*cp == ' ')
+ cp++;
+ strcpy(cmd_path, cp);
+ if (cp = index(cmd_path, ' '))
+ *cp++ = '\0';
+ strcpy(cmd, "ex ");
+ strcat(cmd, cmd_path);
+ if (cp)
+ {
+ strcat(cmd, " ");
+ strcat(cmd, cp);
+ }
+ argv[0] = shell;
+ argv[1] = cmd;
+ /*
+ mode is "r" (stdout) or "w" (stdin)
+ */
+ switch(mode[0])
+ {
+ case 'w': fd = 0;
+ break;
+ case 'r': fd = 1;
+ break;
+ default: return(NULL);
+ }
+ if (fd == 1)
+ fflush(stdout);
+ fdsav = dup(fd);
+ close(fd);
+
+ creat("/pipe", S_IWRITE+S_IREAD);
+ pid = os9exec(os9forkc, argv[0], argv, environ, 0, 0, 3);
+ fd2 = dup(fd);
+ close(fd);
+ dup(fdsav);
+ close(fdsav);
+ if (pid > 0)
+ {
+ pids[fd2] = pid;
+ r = fdopen(fd2, mode);
+ }
+ else
+ {
+ close(fd2);
+ r = NULL;
+ }
+ return(r);
+}
+
+/*
+ * p c l o s e
+ */
+int pclose(fp)
+ FILE *fp;
+{
+ unsigned int status;
+ int pid;
+ int fd,
+ i;
+ fd = fileno(fp);
+ if (pids[fd] == 0)
+ return(-1);
+ fflush(fp);
+ fclose(fp);
+ while ((pid = wait(&status)) != -1)
+ if (pid == pids[fd])
+ break;
+ else
+ for (i = 0; i < _NFILE; i++)
+ if (pids[i] == pid)
+ {
+ pids[i] = 0;
+ break;
+ }
+ if (pid == -1)
+ status = -1;
+ pids[fd] = 0;
+ return(status);
+}
+#endif /* _OSK */
OpenPOWER on IntegriCloud