Annotation of src/usr.bin/more/os.c, Revision 1.1.1.1
1.1 deraadt 1: /*
2: * Copyright (c) 1988 Mark Nudleman
3: * Copyright (c) 1988 Regents of the University of California.
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
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.
21: *
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
32: * SUCH DAMAGE.
33: */
34:
35: #ifndef lint
36: /* from: static char sccsid[] = "@(#)os.c 5.12 (Berkeley) 3/1/91"; */
37: static char *rcsid = "$Id: os.c,v 1.3 1994/12/24 17:17:10 cgd Exp $";
38: #endif /* not lint */
39:
40: /*
41: * Operating system dependent routines.
42: *
43: * Most of the stuff in here is based on Unix, but an attempt
44: * has been made to make things work on other operating systems.
45: * This will sometimes result in a loss of functionality, unless
46: * someone rewrites code specifically for the new operating system.
47: *
48: * The makefile provides defines to decide whether various
49: * Unix features are present.
50: */
51:
52: #include <sys/param.h>
53: #include <sys/stat.h>
54: #include <sys/file.h>
55: #include <signal.h>
56: #include <setjmp.h>
57: #include <stdio.h>
58: #include <string.h>
59: #include <less.h>
60: #include "pathnames.h"
61:
62: int reading;
63:
64: extern int screen_trashed;
65:
66: static jmp_buf read_label;
67:
68: /*
69: * Pass the specified command to a shell to be executed.
70: * Like plain "system()", but handles resetting terminal modes, etc.
71: */
72: lsystem(cmd)
73: char *cmd;
74: {
75: int inp;
76: char cmdbuf[256];
77: char *shell, *getenv();
78:
79: /*
80: * Print the command which is to be executed,
81: * unless the command starts with a "-".
82: */
83: if (cmd[0] == '-')
84: cmd++;
85: else
86: {
87: lower_left();
88: clear_eol();
89: putstr("!");
90: putstr(cmd);
91: putstr("\n");
92: }
93:
94: /*
95: * De-initialize the terminal and take out of raw mode.
96: */
97: deinit();
98: flush();
99: raw_mode(0);
100:
101: /*
102: * Restore signals to their defaults.
103: */
104: init_signals(0);
105:
106: /*
107: * Force standard input to be the terminal, "/dev/tty",
108: * even if less's standard input is coming from a pipe.
109: */
110: inp = dup(0);
111: (void)close(0);
112: if (open(_PATH_TTY, O_RDONLY, 0) < 0)
113: (void)dup(inp);
114:
115: /*
116: * Pass the command to the system to be executed.
117: * If we have a SHELL environment variable, use
118: * <$SHELL -c "command"> instead of just <command>.
119: * If the command is empty, just invoke a shell.
120: */
121: if ((shell = getenv("SHELL")) != NULL && *shell != '\0')
122: {
123: if (*cmd == '\0')
124: cmd = shell;
125: else
126: {
127: (void)sprintf(cmdbuf, "%s -c \"%s\"", shell, cmd);
128: cmd = cmdbuf;
129: }
130: }
131: if (*cmd == '\0')
132: cmd = "sh";
133:
134: (void)system(cmd);
135:
136: /*
137: * Restore standard input, reset signals, raw mode, etc.
138: */
139: (void)close(0);
140: (void)dup(inp);
141: (void)close(inp);
142:
143: init_signals(1);
144: raw_mode(1);
145: init();
146: screen_trashed = 1;
147: #if defined(SIGWINCH) || defined(SIGWIND)
148: /*
149: * Since we were ignoring window change signals while we executed
150: * the system command, we must assume the window changed.
151: */
152: winch();
153: #endif
154: }
155:
156: /*
157: * Like read() system call, but is deliberately interruptable.
158: * A call to intread() from a signal handler will interrupt
159: * any pending iread().
160: */
161: iread(fd, buf, len)
162: int fd;
163: char *buf;
164: int len;
165: {
166: register int n;
167:
168: if (setjmp(read_label))
169: /*
170: * We jumped here from intread.
171: */
172: return (READ_INTR);
173:
174: flush();
175: reading = 1;
176: n = read(fd, buf, len);
177: reading = 0;
178: if (n < 0)
179: return (-1);
180: return (n);
181: }
182:
183: intread()
184: {
185: (void)sigsetmask(0L);
186: longjmp(read_label, 1);
187: }
188:
189: /*
190: * Expand a filename, substituting any environment variables, etc.
191: * The implementation of this is necessarily very operating system
192: * dependent. This implementation is unabashedly only for Unix systems.
193: */
194: FILE *popen();
195:
196: char *
197: glob(filename)
198: char *filename;
199: {
200: FILE *f;
201: char *p;
202: int ch;
203: char *cmd, *malloc(), *getenv();
204: static char buffer[MAXPATHLEN];
205:
206: if (filename[0] == '#')
207: return (filename);
208:
209: /*
210: * We get the shell to expand the filename for us by passing
211: * an "echo" command to the shell and reading its output.
212: */
213: p = getenv("SHELL");
214: if (p == NULL || *p == '\0')
215: {
216: /*
217: * Read the output of <echo filename>.
218: */
219: cmd = malloc((u_int)(strlen(filename)+8));
220: if (cmd == NULL)
221: return (filename);
222: (void)sprintf(cmd, "echo \"%s\"", filename);
223: } else
224: {
225: /*
226: * Read the output of <$SHELL -c "echo filename">.
227: */
228: cmd = malloc((u_int)(strlen(p)+12));
229: if (cmd == NULL)
230: return (filename);
231: (void)sprintf(cmd, "%s -c \"echo %s\"", p, filename);
232: }
233:
234: if ((f = popen(cmd, "r")) == NULL)
235: return (filename);
236: free(cmd);
237:
238: for (p = buffer; p < &buffer[sizeof(buffer)-1]; p++)
239: {
240: if ((ch = getc(f)) == '\n' || ch == EOF)
241: break;
242: *p = ch;
243: }
244: *p = '\0';
245: (void)pclose(f);
246: return(buffer);
247: }
248:
249: char *
250: bad_file(filename, message, len)
251: char *filename, *message;
252: u_int len;
253: {
254: extern int errno;
255: struct stat statbuf;
256: char *strcat(), *strerror();
257:
258: if (stat(filename, &statbuf) < 0) {
259: (void)sprintf(message, "%s: %s", filename, strerror(errno));
260: return(message);
261: }
262: if ((statbuf.st_mode & S_IFMT) == S_IFDIR) {
263: static char is_dir[] = " is a directory";
264:
265: strtcpy(message, filename, (int)(len-sizeof(is_dir)-1));
266: (void)strcat(message, is_dir);
267: return(message);
268: }
269: return((char *)NULL);
270: }
271:
272: /*
273: * Copy a string, truncating to the specified length if necessary.
274: * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
275: */
276: strtcpy(to, from, len)
277: char *to, *from;
278: int len;
279: {
280: char *strncpy();
281:
282: (void)strncpy(to, from, (int)len);
283: to[len-1] = '\0';
284: }
285: