xref: /csrg-svn/usr.bin/more/os.c (revision 62131)
135209Sbostic /*
235209Sbostic  * Copyright (c) 1988 Mark Nudleman
3*62131Sbostic  * Copyright (c) 1988, 1993
4*62131Sbostic  *	The Regents of the University of California.  All rights reserved.
535209Sbostic  *
642742Sbostic  * %sccs.include.redist.c%
735209Sbostic  */
835209Sbostic 
935209Sbostic #ifndef lint
10*62131Sbostic static char sccsid[] = "@(#)os.c	8.1 (Berkeley) 06/06/93";
1135209Sbostic #endif /* not lint */
1235209Sbostic 
1335209Sbostic /*
1435209Sbostic  * Operating system dependent routines.
1535209Sbostic  *
1635209Sbostic  * Most of the stuff in here is based on Unix, but an attempt
1735209Sbostic  * has been made to make things work on other operating systems.
1835209Sbostic  * This will sometimes result in a loss of functionality, unless
1935209Sbostic  * someone rewrites code specifically for the new operating system.
2035209Sbostic  *
2135209Sbostic  * The makefile provides defines to decide whether various
2235209Sbostic  * Unix features are present.
2335209Sbostic  */
2435209Sbostic 
2536253Sbostic #include <sys/param.h>
2636253Sbostic #include <sys/stat.h>
2736253Sbostic #include <sys/file.h>
2835209Sbostic #include <signal.h>
2935209Sbostic #include <setjmp.h>
3036253Sbostic #include <stdio.h>
3136253Sbostic #include <less.h>
3237919Sbostic #include "pathnames.h"
3335209Sbostic 
3436253Sbostic int reading;
3535209Sbostic 
3635209Sbostic extern int screen_trashed;
3735209Sbostic 
3835209Sbostic static jmp_buf read_label;
3935209Sbostic 
4035209Sbostic /*
4135209Sbostic  * Pass the specified command to a shell to be executed.
4235209Sbostic  * Like plain "system()", but handles resetting terminal modes, etc.
4335209Sbostic  */
lsystem(cmd)4435209Sbostic lsystem(cmd)
4535209Sbostic 	char *cmd;
4635209Sbostic {
4735209Sbostic 	int inp;
4835209Sbostic 	char cmdbuf[256];
4936253Sbostic 	char *shell, *getenv();
5035209Sbostic 
5135209Sbostic 	/*
5235209Sbostic 	 * Print the command which is to be executed,
5335209Sbostic 	 * unless the command starts with a "-".
5435209Sbostic 	 */
5535209Sbostic 	if (cmd[0] == '-')
5635209Sbostic 		cmd++;
5735209Sbostic 	else
5835209Sbostic 	{
5935209Sbostic 		lower_left();
6035209Sbostic 		clear_eol();
6135209Sbostic 		putstr("!");
6235209Sbostic 		putstr(cmd);
6335209Sbostic 		putstr("\n");
6435209Sbostic 	}
6535209Sbostic 
6635209Sbostic 	/*
6735209Sbostic 	 * De-initialize the terminal and take out of raw mode.
6835209Sbostic 	 */
6935209Sbostic 	deinit();
7035209Sbostic 	flush();
7135209Sbostic 	raw_mode(0);
7235209Sbostic 
7335209Sbostic 	/*
7435209Sbostic 	 * Restore signals to their defaults.
7535209Sbostic 	 */
7635209Sbostic 	init_signals(0);
7735209Sbostic 
7835209Sbostic 	/*
7935209Sbostic 	 * Force standard input to be the terminal, "/dev/tty",
8035209Sbostic 	 * even if less's standard input is coming from a pipe.
8135209Sbostic 	 */
8235209Sbostic 	inp = dup(0);
8336253Sbostic 	(void)close(0);
8437919Sbostic 	if (open(_PATH_TTY, O_RDONLY, 0) < 0)
8536253Sbostic 		(void)dup(inp);
8635209Sbostic 
8735209Sbostic 	/*
8835209Sbostic 	 * Pass the command to the system to be executed.
8935209Sbostic 	 * If we have a SHELL environment variable, use
9035209Sbostic 	 * <$SHELL -c "command"> instead of just <command>.
9135209Sbostic 	 * If the command is empty, just invoke a shell.
9235209Sbostic 	 */
9335209Sbostic 	if ((shell = getenv("SHELL")) != NULL && *shell != '\0')
9435209Sbostic 	{
9535209Sbostic 		if (*cmd == '\0')
9635209Sbostic 			cmd = shell;
9735209Sbostic 		else
9835209Sbostic 		{
9935244Sbostic 			(void)sprintf(cmdbuf, "%s -c \"%s\"", shell, cmd);
10035209Sbostic 			cmd = cmdbuf;
10135209Sbostic 		}
10235209Sbostic 	}
10335209Sbostic 	if (*cmd == '\0')
10435209Sbostic 		cmd = "sh";
10535209Sbostic 
10636253Sbostic 	(void)system(cmd);
10735209Sbostic 
10835209Sbostic 	/*
10935209Sbostic 	 * Restore standard input, reset signals, raw mode, etc.
11035209Sbostic 	 */
11136253Sbostic 	(void)close(0);
11236253Sbostic 	(void)dup(inp);
11336253Sbostic 	(void)close(inp);
11435209Sbostic 
11535209Sbostic 	init_signals(1);
11635209Sbostic 	raw_mode(1);
11735209Sbostic 	init();
11835209Sbostic 	screen_trashed = 1;
11935209Sbostic #if defined(SIGWINCH) || defined(SIGWIND)
12035209Sbostic 	/*
12135209Sbostic 	 * Since we were ignoring window change signals while we executed
12235209Sbostic 	 * the system command, we must assume the window changed.
12335209Sbostic 	 */
12435209Sbostic 	winch();
12535209Sbostic #endif
12635209Sbostic }
12735209Sbostic 
12835209Sbostic /*
12935209Sbostic  * Like read() system call, but is deliberately interruptable.
13035209Sbostic  * A call to intread() from a signal handler will interrupt
13135209Sbostic  * any pending iread().
13235209Sbostic  */
iread(fd,buf,len)13335209Sbostic iread(fd, buf, len)
13435209Sbostic 	int fd;
13535209Sbostic 	char *buf;
13635209Sbostic 	int len;
13735209Sbostic {
13835209Sbostic 	register int n;
13935209Sbostic 
14035209Sbostic 	if (setjmp(read_label))
14135209Sbostic 		/*
14235209Sbostic 		 * We jumped here from intread.
14335209Sbostic 		 */
14435209Sbostic 		return (READ_INTR);
14535209Sbostic 
14635209Sbostic 	flush();
14735209Sbostic 	reading = 1;
14835209Sbostic 	n = read(fd, buf, len);
14935209Sbostic 	reading = 0;
15035209Sbostic 	if (n < 0)
15135209Sbostic 		return (-1);
15235209Sbostic 	return (n);
15335209Sbostic }
15435209Sbostic 
intread()15535209Sbostic intread()
15635209Sbostic {
15736253Sbostic 	(void)sigsetmask(0L);
15835209Sbostic 	longjmp(read_label, 1);
15935209Sbostic }
16035209Sbostic 
16135209Sbostic /*
16235209Sbostic  * Expand a filename, substituting any environment variables, etc.
16335209Sbostic  * The implementation of this is necessarily very operating system
16435209Sbostic  * dependent.  This implementation is unabashedly only for Unix systems.
16535209Sbostic  */
16635209Sbostic FILE *popen();
16735209Sbostic 
16836253Sbostic char *
glob(filename)16935209Sbostic glob(filename)
17035209Sbostic 	char *filename;
17135209Sbostic {
17235209Sbostic 	FILE *f;
17335209Sbostic 	char *p;
17435209Sbostic 	int ch;
17536253Sbostic 	char *cmd, *malloc(), *getenv();
17636253Sbostic 	static char buffer[MAXPATHLEN];
17735209Sbostic 
17835209Sbostic 	if (filename[0] == '#')
17935209Sbostic 		return (filename);
18035209Sbostic 
18135209Sbostic 	/*
18235209Sbostic 	 * We get the shell to expand the filename for us by passing
18335209Sbostic 	 * an "echo" command to the shell and reading its output.
18435209Sbostic 	 */
18535209Sbostic 	p = getenv("SHELL");
18635209Sbostic 	if (p == NULL || *p == '\0')
18735209Sbostic 	{
18835209Sbostic 		/*
18935209Sbostic 		 * Read the output of <echo filename>.
19035209Sbostic 		 */
19135244Sbostic 		cmd = malloc((u_int)(strlen(filename)+8));
19235209Sbostic 		if (cmd == NULL)
19335209Sbostic 			return (filename);
19435244Sbostic 		(void)sprintf(cmd, "echo \"%s\"", filename);
19535209Sbostic 	} else
19635209Sbostic 	{
19735209Sbostic 		/*
19835209Sbostic 		 * Read the output of <$SHELL -c "echo filename">.
19935209Sbostic 		 */
20035244Sbostic 		cmd = malloc((u_int)(strlen(p)+12));
20135209Sbostic 		if (cmd == NULL)
20235209Sbostic 			return (filename);
20335244Sbostic 		(void)sprintf(cmd, "%s -c \"echo %s\"", p, filename);
20435209Sbostic 	}
20535209Sbostic 
20635209Sbostic 	if ((f = popen(cmd, "r")) == NULL)
20735209Sbostic 		return (filename);
20835209Sbostic 	free(cmd);
20935209Sbostic 
21035209Sbostic 	for (p = buffer;  p < &buffer[sizeof(buffer)-1];  p++)
21135209Sbostic 	{
21235209Sbostic 		if ((ch = getc(f)) == '\n' || ch == EOF)
21335209Sbostic 			break;
21435209Sbostic 		*p = ch;
21535209Sbostic 	}
21635209Sbostic 	*p = '\0';
21736253Sbostic 	(void)pclose(f);
21836253Sbostic 	return(buffer);
21935209Sbostic }
22035209Sbostic 
22136253Sbostic char *
bad_file(filename,message,len)22235209Sbostic bad_file(filename, message, len)
22336253Sbostic 	char *filename, *message;
22436253Sbostic 	u_int len;
22535209Sbostic {
22636253Sbostic 	extern int errno;
22735209Sbostic 	struct stat statbuf;
22836253Sbostic 	char *strcat(), *strerror();
22935209Sbostic 
23036253Sbostic 	if (stat(filename, &statbuf) < 0) {
23136253Sbostic 		(void)sprintf(message, "%s: %s", filename, strerror(errno));
23236253Sbostic 		return(message);
23336253Sbostic 	}
23436253Sbostic 	if ((statbuf.st_mode & S_IFMT) == S_IFDIR) {
23536253Sbostic 		static char is_dir[] = " is a directory";
23635209Sbostic 
23736253Sbostic 		strtcpy(message, filename, (int)(len-sizeof(is_dir)-1));
23835244Sbostic 		(void)strcat(message, is_dir);
23936253Sbostic 		return(message);
24035209Sbostic 	}
24136253Sbostic 	return((char *)NULL);
24235209Sbostic }
24335209Sbostic 
24435209Sbostic /*
24536253Sbostic  * Copy a string, truncating to the specified length if necessary.
24636253Sbostic  * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
24735209Sbostic  */
strtcpy(to,from,len)24836253Sbostic strtcpy(to, from, len)
24936253Sbostic 	char *to, *from;
25036253Sbostic 	int len;
25135209Sbostic {
25236253Sbostic 	char *strncpy();
25335209Sbostic 
25436253Sbostic 	(void)strncpy(to, from, (int)len);
25536253Sbostic 	to[len-1] = '\0';
25635209Sbostic }
25736253Sbostic 
258