2 * Copyright (c) 1988 Mark Nudleman
3 * Copyright (c) 1988, 1993
4 * The Regents of the University of California. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 static char sccsid[] = "@(#)os.c 8.1 (Berkeley) 6/6/93";
40 * Operating system dependent routines.
42 * Most of the stuff in here is based on Unix, but an attempt
43 * has been made to make things work on other operating systems.
44 * This will sometimes result in a loss of functionality, unless
45 * someone rewrites code specifically for the new operating system.
47 * The makefile provides defines to decide whether various
48 * Unix features are present.
51 #include <sys/param.h>
58 #include "pathnames.h"
62 extern int screen_trashed;
64 static jmp_buf read_label;
67 * Pass the specified command to a shell to be executed.
68 * Like plain "system()", but handles resetting terminal modes, etc.
75 char *shell, *getenv();
78 * Print the command which is to be executed,
79 * unless the command starts with a "-".
93 * De-initialize the terminal and take out of raw mode.
100 * Restore signals to their defaults.
105 * Force standard input to be the terminal, "/dev/tty",
106 * even if less's standard input is coming from a pipe.
110 if (open(_PATH_TTY, O_RDONLY, 0) < 0)
114 * Pass the command to the system to be executed.
115 * If we have a SHELL environment variable, use
116 * <$SHELL -c "command"> instead of just <command>.
117 * If the command is empty, just invoke a shell.
119 if ((shell = getenv("SHELL")) != NULL && *shell != '\0')
125 (void)sprintf(cmdbuf, "%s -c \"%s\"", shell, cmd);
135 * Restore standard input, reset signals, raw mode, etc.
145 #if defined(SIGWINCH) || defined(SIGWIND)
147 * Since we were ignoring window change signals while we executed
148 * the system command, we must assume the window changed.
155 * Like read() system call, but is deliberately interruptable.
156 * A call to intread() from a signal handler will interrupt
157 * any pending iread().
166 if (setjmp(read_label))
168 * We jumped here from intread.
174 n = read(fd, buf, len);
183 (void)sigsetmask(0L);
184 longjmp(read_label, 1);
188 * Expand a filename, substituting any environment variables, etc.
189 * The implementation of this is necessarily very operating system
190 * dependent. This implementation is unabashedly only for Unix systems.
201 char *cmd, *malloc(), *getenv();
202 static char buffer[MAXPATHLEN];
204 if (filename[0] == '#')
208 * We get the shell to expand the filename for us by passing
209 * an "echo" command to the shell and reading its output.
212 if (p == NULL || *p == '\0')
215 * Read the output of <echo filename>.
217 cmd = malloc((u_int)(strlen(filename)+8));
220 (void)sprintf(cmd, "echo \"%s\"", filename);
224 * Read the output of <$SHELL -c "echo filename">.
226 cmd = malloc((u_int)(strlen(p)+12));
229 (void)sprintf(cmd, "%s -c \"echo %s\"", p, filename);
232 if ((f = popen(cmd, "r")) == NULL)
236 for (p = buffer; p < &buffer[sizeof(buffer)-1]; p++)
238 if ((ch = getc(f)) == '\n' || ch == EOF)
248 bad_file(filename, message, len)
249 char *filename, *message;
254 char *strcat(), *strerror();
256 if (stat(filename, &statbuf) < 0) {
257 (void)sprintf(message, "%s: %s", filename, strerror(errno));
260 if ((statbuf.st_mode & S_IFMT) == S_IFDIR) {
261 static char is_dir[] = " is a directory";
263 strtcpy(message, filename, (int)(len-sizeof(is_dir)-1));
264 (void)strcat(message, is_dir);
267 return((char *)NULL);
271 * Copy a string, truncating to the specified length if necessary.
272 * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
274 strtcpy(to, from, len)
280 (void)strncpy(to, from, (int)len);