rip out GLOB define; make default
[unix-history] / usr / src / usr.bin / more / os.c
CommitLineData
bfe13c81
KB
1/*
2 * Copyright (c) 1988 Mark Nudleman
3 * Copyright (c) 1988 Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Mark Nudleman.
8 *
9 * Redistribution and use in source and binary forms are permitted
10 * provided that the above copyright notice and this paragraph are
11 * duplicated in all such forms and that any documentation,
12 * advertising materials, and other materials related to such
13 * distribution and use acknowledge that the software was developed
14 * by the University of California, Berkeley. The name of the
15 * University may not be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
19 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22#ifndef lint
9e61ffac 23static char sccsid[] = "@(#)os.c 5.6 (Berkeley) %G%";
bfe13c81
KB
24#endif /* not lint */
25
26/*
27 * Operating system dependent routines.
28 *
29 * Most of the stuff in here is based on Unix, but an attempt
30 * has been made to make things work on other operating systems.
31 * This will sometimes result in a loss of functionality, unless
32 * someone rewrites code specifically for the new operating system.
33 *
34 * The makefile provides defines to decide whether various
35 * Unix features are present.
36 */
37
38#include <stdio.h>
39#include <signal.h>
40#include <setjmp.h>
41#include "less.h"
42
43char *getenv();
44
45public int reading;
46
47extern int screen_trashed;
48
49static jmp_buf read_label;
50
51/*
52 * Pass the specified command to a shell to be executed.
53 * Like plain "system()", but handles resetting terminal modes, etc.
54 */
55 public void
56lsystem(cmd)
57 char *cmd;
58{
59 int inp;
60 char cmdbuf[256];
61 char *shell;
62
63 /*
64 * Print the command which is to be executed,
65 * unless the command starts with a "-".
66 */
67 if (cmd[0] == '-')
68 cmd++;
69 else
70 {
71 lower_left();
72 clear_eol();
73 putstr("!");
74 putstr(cmd);
75 putstr("\n");
76 }
77
78 /*
79 * De-initialize the terminal and take out of raw mode.
80 */
81 deinit();
82 flush();
83 raw_mode(0);
84
85 /*
86 * Restore signals to their defaults.
87 */
88 init_signals(0);
89
90 /*
91 * Force standard input to be the terminal, "/dev/tty",
92 * even if less's standard input is coming from a pipe.
93 */
94 inp = dup(0);
95 close(0);
96 if (open("/dev/tty", 0) < 0)
97 dup(inp);
98
99 /*
100 * Pass the command to the system to be executed.
101 * If we have a SHELL environment variable, use
102 * <$SHELL -c "command"> instead of just <command>.
103 * If the command is empty, just invoke a shell.
104 */
105 if ((shell = getenv("SHELL")) != NULL && *shell != '\0')
106 {
107 if (*cmd == '\0')
108 cmd = shell;
109 else
110 {
111 sprintf(cmdbuf, "%s -c \"%s\"", shell, cmd);
112 cmd = cmdbuf;
113 }
114 }
115 if (*cmd == '\0')
116 cmd = "sh";
117
118 system(cmd);
119
120 /*
121 * Restore standard input, reset signals, raw mode, etc.
122 */
123 close(0);
124 dup(inp);
125 close(inp);
126
127 init_signals(1);
128 raw_mode(1);
129 init();
130 screen_trashed = 1;
131#if defined(SIGWINCH) || defined(SIGWIND)
132 /*
133 * Since we were ignoring window change signals while we executed
134 * the system command, we must assume the window changed.
135 */
136 winch();
137#endif
138}
139
140/*
141 * Like read() system call, but is deliberately interruptable.
142 * A call to intread() from a signal handler will interrupt
143 * any pending iread().
144 */
145 public int
146iread(fd, buf, len)
147 int fd;
148 char *buf;
149 int len;
150{
151 register int n;
152
153 if (setjmp(read_label))
154 /*
155 * We jumped here from intread.
156 */
157 return (READ_INTR);
158
159 flush();
160 reading = 1;
161 n = read(fd, buf, len);
162 reading = 0;
163 if (n < 0)
164 return (-1);
165 return (n);
166}
167
168 public void
169intread()
170{
8e70b0c4 171 sigsetmask(0L);
bfe13c81
KB
172 longjmp(read_label, 1);
173}
174
bfe13c81
KB
175 public long
176get_time()
177{
54795006 178 time_t time();
bfe13c81 179
54795006 180 return(time((long *)NULL));
bfe13c81 181}
bfe13c81
KB
182
183/*
184 * Expand a filename, substituting any environment variables, etc.
185 * The implementation of this is necessarily very operating system
186 * dependent. This implementation is unabashedly only for Unix systems.
187 */
bfe13c81
KB
188FILE *popen();
189
190 public char *
191glob(filename)
192 char *filename;
193{
194 FILE *f;
195 char *p;
196 int ch;
197 char *cmd;
198 static char buffer[FILENAME];
199
200 if (filename[0] == '#')
201 return (filename);
202
203 /*
204 * We get the shell to expand the filename for us by passing
205 * an "echo" command to the shell and reading its output.
206 */
207 p = getenv("SHELL");
208 if (p == NULL || *p == '\0')
209 {
210 /*
211 * Read the output of <echo filename>.
212 */
213 cmd = calloc(strlen(filename)+8, sizeof(char));
214 if (cmd == NULL)
215 return (filename);
216 sprintf(cmd, "echo \"%s\"", filename);
217 } else
218 {
219 /*
220 * Read the output of <$SHELL -c "echo filename">.
221 */
222 cmd = calloc(strlen(p)+12);
223 if (cmd == NULL)
224 return (filename);
225 sprintf(cmd, "%s -c \"echo %s\"", p, filename);
226 }
227
228 if ((f = popen(cmd, "r")) == NULL)
229 return (filename);
230 free(cmd);
231
232 for (p = buffer; p < &buffer[sizeof(buffer)-1]; p++)
233 {
234 if ((ch = getc(f)) == '\n' || ch == EOF)
235 break;
236 *p = ch;
237 }
238 *p = '\0';
239 pclose(f);
240 return (buffer);
241}
242
bfe13c81
KB
243/*
244 * Returns NULL if the file can be opened and
245 * is an ordinary file, otherwise an error message
246 * (if it cannot be opened or is a directory, etc.)
247 */
248
bfe13c81
KB
249#include <sys/types.h>
250#include <sys/stat.h>
251
252 public char *
253bad_file(filename, message, len)
254 char *filename;
255 char *message;
256 unsigned int len;
257{
258 struct stat statbuf;
259
260 if (stat(filename, &statbuf) < 0)
261 return (errno_message(filename, message, len));
262
263 if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
264 {
265 static char is_dir[] = " is a directory";
266 strtcpy(message, filename, len-sizeof(is_dir)-1);
267 strcat(message, is_dir);
268 return (message);
269 }
270 if ((statbuf.st_mode & S_IFMT) != S_IFREG)
271 {
272 static char not_reg[] = " is not a regular file";
273 strtcpy(message, filename, len-sizeof(not_reg)-1);
274 strcat(message, not_reg);
275 return (message);
276 }
277 return (NULL);
278}
279
bfe13c81
KB
280/*
281 * errno_message: Return an error message based on the value of "errno".
282 * okreadfail: Return true if the previous failure of a read
283 * (on the input tty) should be considered ok.
284 */
285
bfe13c81
KB
286extern char *sys_errlist[];
287extern int sys_nerr;
288extern int errno;
289
290 public char *
291errno_message(filename, message, len)
292 char *filename;
293 char *message;
294 unsigned int len;
295{
296 char *p;
297 char msg[16];
298
299 if (errno < sys_nerr)
300 p = sys_errlist[errno];
301 else
302 {
303 sprintf(msg, "Error %d", errno);
304 p = msg;
305 }
306 strtcpy(message, filename, len-strlen(p)-3);
307 strcat(message, ": ");
308 strcat(message, p);
309 return (message);
310}