* Copyright (c) 1988 Mark Nudleman
* Copyright (c) 1988 Regents of the University of California.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)os.c 5.11 (Berkeley) %G%";
* Operating system dependent routines.
* Most of the stuff in here is based on Unix, but an attempt
* has been made to make things work on other operating systems.
* This will sometimes result in a loss of functionality, unless
* someone rewrites code specifically for the new operating system.
* The makefile provides defines to decide whether various
* Unix features are present.
extern int screen_trashed
;
static jmp_buf read_label
;
* Pass the specified command to a shell to be executed.
* Like plain "system()", but handles resetting terminal modes, etc.
* Print the command which is to be executed,
* unless the command starts with a "-".
* De-initialize the terminal and take out of raw mode.
* Restore signals to their defaults.
* Force standard input to be the terminal, "/dev/tty",
* even if less's standard input is coming from a pipe.
if (open(_PATH_TTY
, O_RDONLY
, 0) < 0)
* 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 ((shell
= getenv("SHELL")) != NULL
&& *shell
!= '\0')
(void)sprintf(cmdbuf
, "%s -c \"%s\"", shell
, cmd
);
* Restore standard input, reset signals, raw mode, etc.
#if defined(SIGWINCH) || defined(SIGWIND)
* Since we were ignoring window change signals while we executed
* the system command, we must assume the window changed.
* Like read() system call, but is deliberately interruptable.
* A call to intread() from a signal handler will interrupt
* We jumped here from intread.
* Expand a filename, substituting any environment variables, etc.
* The implementation of this is necessarily very operating system
* dependent. This implementation is unabashedly only for Unix systems.
char *cmd
, *malloc(), *getenv();
static char buffer
[MAXPATHLEN
];
* We get the shell to expand the filename for us by passing
* an "echo" command to the shell and reading its output.
if (p
== NULL
|| *p
== '\0')
* Read the output of <echo filename>.
cmd
= malloc((u_int
)(strlen(filename
)+8));
(void)sprintf(cmd
, "echo \"%s\"", filename
);
* Read the output of <$SHELL -c "echo filename">.
cmd
= malloc((u_int
)(strlen(p
)+12));
(void)sprintf(cmd
, "%s -c \"echo %s\"", p
, filename
);
if ((f
= popen(cmd
, "r")) == NULL
)
for (p
= buffer
; p
< &buffer
[sizeof(buffer
)-1]; p
++)
if ((ch
= getc(f
)) == '\n' || ch
== EOF
)
bad_file(filename
, message
, len
)
char *filename
, *message
;
char *strcat(), *strerror();
if (stat(filename
, &statbuf
) < 0) {
(void)sprintf(message
, "%s: %s", filename
, strerror(errno
));
if ((statbuf
.st_mode
& S_IFMT
) == S_IFDIR
) {
static char is_dir
[] = " is a directory";
strtcpy(message
, filename
, (int)(len
-sizeof(is_dir
)-1));
(void)strcat(message
, is_dir
);
* Copy a string, truncating to the specified length if necessary.
* Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
(void)strncpy(to
, from
, (int)len
);