rip out USERFILE, 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
8e70b0c4 23static char sccsid[] = "@(#)os.c 5.5 (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 */
188#if GLOB
189
190FILE *popen();
191
192 public char *
193glob(filename)
194 char *filename;
195{
196 FILE *f;
197 char *p;
198 int ch;
199 char *cmd;
200 static char buffer[FILENAME];
201
202 if (filename[0] == '#')
203 return (filename);
204
205 /*
206 * We get the shell to expand the filename for us by passing
207 * an "echo" command to the shell and reading its output.
208 */
209 p = getenv("SHELL");
210 if (p == NULL || *p == '\0')
211 {
212 /*
213 * Read the output of <echo filename>.
214 */
215 cmd = calloc(strlen(filename)+8, sizeof(char));
216 if (cmd == NULL)
217 return (filename);
218 sprintf(cmd, "echo \"%s\"", filename);
219 } else
220 {
221 /*
222 * Read the output of <$SHELL -c "echo filename">.
223 */
224 cmd = calloc(strlen(p)+12);
225 if (cmd == NULL)
226 return (filename);
227 sprintf(cmd, "%s -c \"echo %s\"", p, filename);
228 }
229
230 if ((f = popen(cmd, "r")) == NULL)
231 return (filename);
232 free(cmd);
233
234 for (p = buffer; p < &buffer[sizeof(buffer)-1]; p++)
235 {
236 if ((ch = getc(f)) == '\n' || ch == EOF)
237 break;
238 *p = ch;
239 }
240 *p = '\0';
241 pclose(f);
242 return (buffer);
243}
244
245#else
246
247 public char *
248glob(filename)
249 char *filename;
250{
251 return (filename);
252}
253
254#endif
255
256
257/*
258 * Returns NULL if the file can be opened and
259 * is an ordinary file, otherwise an error message
260 * (if it cannot be opened or is a directory, etc.)
261 */
262
bfe13c81
KB
263#include <sys/types.h>
264#include <sys/stat.h>
265
266 public char *
267bad_file(filename, message, len)
268 char *filename;
269 char *message;
270 unsigned int len;
271{
272 struct stat statbuf;
273
274 if (stat(filename, &statbuf) < 0)
275 return (errno_message(filename, message, len));
276
277 if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
278 {
279 static char is_dir[] = " is a directory";
280 strtcpy(message, filename, len-sizeof(is_dir)-1);
281 strcat(message, is_dir);
282 return (message);
283 }
284 if ((statbuf.st_mode & S_IFMT) != S_IFREG)
285 {
286 static char not_reg[] = " is not a regular file";
287 strtcpy(message, filename, len-sizeof(not_reg)-1);
288 strcat(message, not_reg);
289 return (message);
290 }
291 return (NULL);
292}
293
bfe13c81
KB
294/*
295 * errno_message: Return an error message based on the value of "errno".
296 * okreadfail: Return true if the previous failure of a read
297 * (on the input tty) should be considered ok.
298 */
299
bfe13c81
KB
300extern char *sys_errlist[];
301extern int sys_nerr;
302extern int errno;
303
304 public char *
305errno_message(filename, message, len)
306 char *filename;
307 char *message;
308 unsigned int len;
309{
310 char *p;
311 char msg[16];
312
313 if (errno < sys_nerr)
314 p = sys_errlist[errno];
315 else
316 {
317 sprintf(msg, "Error %d", errno);
318 p = msg;
319 }
320 strtcpy(message, filename, len-strlen(p)-3);
321 strcat(message, ": ");
322 strcat(message, p);
323 return (message);
324}