summaryrefslogtreecommitdiff
path: root/usr.bin/less/lsystem.c
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2003-04-13 18:26:27 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2003-04-13 18:26:27 +0000
commit5569f8a6b6c831077f77d24e2c23d2e2d41fb95f (patch)
treeb79fe763d81906631382fbdc80f3b42a44b6c668 /usr.bin/less/lsystem.c
parent6b9d6b99a4fdda2ee6d9a30dec452d8202fb2017 (diff)
Merge in less-381 w/ local changes and remove obsolete files.
Diffstat (limited to 'usr.bin/less/lsystem.c')
-rw-r--r--usr.bin/less/lsystem.c314
1 files changed, 261 insertions, 53 deletions
diff --git a/usr.bin/less/lsystem.c b/usr.bin/less/lsystem.c
index 9e39a8ed1fe..8fa4683215e 100644
--- a/usr.bin/less/lsystem.c
+++ b/usr.bin/less/lsystem.c
@@ -1,29 +1,11 @@
-/* $OpenBSD: lsystem.c,v 1.4 2003/04/06 23:38:07 deraadt Exp $ */
-
/*
- * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
- * All rights reserved.
+ * Copyright (C) 1984-2002 Mark Nudelman
*
- * 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.
+ * You may distribute under the terms of either the GNU General Public
+ * License or the Less License, as specified in the README file.
*
- * 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.
+ * For more information about less, or for information on how to
+ * contact the author, see the README file.
*/
@@ -32,12 +14,18 @@
* Necessarily very OS dependent.
*/
-#include <signal.h>
#include "less.h"
+#include <signal.h>
#include "position.h"
-#if MSOFTC
+#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;
@@ -51,16 +39,19 @@ extern IFILE curr_ifile;
* Like plain "system()", but handles resetting terminal modes, etc.
*/
public void
-lsystem(cmd)
+lsystem(cmd, donemsg)
char *cmd;
+ char *donemsg;
{
- int inp;
-#if MSOFTC || OS2
- int inp2;
+ register int inp;
+#if HAVE_SHELL
+ register char *shell;
+ register char *p;
#endif
- char *shell;
- char *p;
IFILE save_ifile;
+#if MSDOS_COMPILER
+ char cwd[FILENAME_MAX+1];
+#endif
/*
* Print the command which is to be executed,
@@ -76,10 +67,21 @@ lsystem(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 = curr_ifile;
+ save_ifile = save_curr_ifile();
(void) edit_ifile(NULL_IFILE);
/*
@@ -88,12 +90,16 @@ lsystem(cmd)
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
@@ -101,8 +107,14 @@ lsystem(cmd)
*/
inp = dup(0);
close(0);
- if (OPEN_TTYIN() < 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.
@@ -112,15 +124,21 @@ lsystem(cmd)
*/
#if HAVE_SHELL
p = NULL;
- if ((shell = getenv("SHELL")) != NULL && *shell != '\0')
+ if ((shell = lgetenv("SHELL")) != NULL && *shell != '\0')
{
if (*cmd == '\0')
p = save(shell);
else
{
- size_t l = strlen(shell) + strlen(cmd) + 7;
- p = (char *) ecalloc(l, sizeof(char));
- snprintf(p, l, "%s -c \"%s\"", shell, cmd);
+ char *esccmd = shell_quote(cmd);
+ if (esccmd != NULL)
+ {
+ size_t len = strlen(shell) + strlen(esccmd) + 5;
+ p = (char *) ecalloc(len, sizeof(char));
+ snprintf(p, len, "%s %s %s", shell,
+ shell_coption(), esccmd);
+ free(esccmd);
+ }
}
}
if (p == NULL)
@@ -130,34 +148,76 @@ lsystem(cmd)
else
p = save(cmd);
}
-
system(p);
free(p);
#else
-#if OS2
- if (*cmd == '\0')
- cmd = "cmd.exe";
-#endif
+#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.
*/
- if (edit_ifile(save_ifile))
- quit(QUIT_ERROR);
+ reedit_ifile(save_ifile);
#if defined(SIGWINCH) || defined(SIGWIND)
/*
@@ -179,10 +239,12 @@ lsystem(cmd)
* 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.
+ * 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)
@@ -207,7 +269,7 @@ pipe_mark(c, cmd)
if (c == '.')
return (pipe_data(cmd, tpos, bpos));
else if (mpos <= tpos)
- return (pipe_data(cmd, mpos, tpos));
+ return (pipe_data(cmd, mpos, bpos));
else if (bpos == NULL_POSITION)
return (pipe_data(cmd, tpos, bpos));
else
@@ -224,8 +286,8 @@ pipe_data(cmd, spos, epos)
POSITION spos;
POSITION epos;
{
- FILE *f;
- int c;
+ register FILE *f;
+ register int c;
extern FILE *popen();
/*
@@ -254,8 +316,11 @@ pipe_data(cmd, spos, epos)
flush();
raw_mode(0);
init_signals(0);
+#if MSDOS_COMPILER==WIN32C
+ close_getchr();
+#endif
#ifdef SIGPIPE
- SIGNAL(SIGPIPE, SIG_IGN);
+ LSIGNAL(SIGPIPE, SIG_IGN);
#endif
c = EOI;
@@ -286,7 +351,10 @@ pipe_data(cmd, spos, epos)
pclose(f);
#ifdef SIGPIPE
- SIGNAL(SIGPIPE, SIG_DFL);
+ LSIGNAL(SIGPIPE, SIG_DFL);
+#endif
+#if MSDOS_COMPILER==WIN32C
+ open_getchr();
#endif
init_signals(1);
raw_mode(1);
@@ -300,3 +368,143 @@ pipe_data(cmd, spos, epos)
}
#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++;
+ strlcpy(cmd_path, cp, sizeof(cmd_path));
+ if (cp = index(cmd_path, ' '))
+ *cp++ = '\0';
+ strlcpy(cmd, "ex ", sizeof(cmd));
+ strlcat(cmd, cmd_path, sizeof(cmd));
+ if (cp)
+ {
+ strlcat(cmd, " ", sizeof(cmd));
+ strlcat(cmd, cp, sizeof(cmd));
+ }
+ 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 */