 84d9c625bf
			
		
	
	
		84d9c625bf
		
	
	
	
	
		
			
			- Fix for possible unset uid/gid in toproto
 - Fix for default mtree style
 - Update libelf
 - Importing libexecinfo
 - Resynchronize GCC, mpc, gmp, mpfr
 - build.sh: Replace params with show-params.
     This has been done as the make target has been renamed in the same
     way, while a new target named params has been added. This new
     target generates a file containing all the parameters, instead of
     printing it on the console.
 - Update test48 with new etc/services (Fix by Ben Gras <ben@minix3.org)
     get getservbyport() out of the inner loop
Change-Id: Ie6ad5226fa2621ff9f0dee8782ea48f9443d2091
		
	
			
		
			
				
	
	
		
			375 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			375 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*	$NetBSD: lsystem.c,v 1.4 2013/09/04 19:44:21 tron Exp $	*/
 | |
| 
 | |
| /*
 | |
|  * 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;
 | |
| 
 | |
| 	/*
 | |
| 	 * 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
 |