]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/miscellany/less-177/filename.c
ap: Fix write past end of addrs[] array.
[nmh] / docs / historical / mh-6.8.5 / miscellany / less-177 / filename.c
1 /*
2 * Routines to mess around with filenames (and files).
3 * Much of this is very OS dependent.
4 */
5
6 #include <stdio.h>
7 #include "less.h"
8
9 extern char *getenv();
10
11 extern int force_open;
12 extern IFILE curr_ifile;
13 extern IFILE old_ifile;
14
15 /*
16 * Return the full pathname of the given file in the "home directory".
17 */
18 public char *
19 homefile(filename)
20 char *filename;
21 {
22 register char *pathname;
23 register char *homedir;
24
25 homedir = getenv("HOME");
26 #if __MSDOS__
27 /*
28 * Most MSDOS users do not have $HOME defined,
29 * so if no $HOME then look for "_less" anywhere
30 * on search path (always begins at current directory).
31 */
32 if (homedir == NULL)
33 {
34 extern char *searchpath();
35 pathname = searchpath(filename);
36 if (pathname == NULL)
37 return (NULL);
38 pathname = save(pathname);
39 } else
40 {
41 pathname = (char *) calloc(strlen(homedir)+strlen(filename)+2,
42 sizeof(char));
43 if (pathname == NULL)
44 return (NULL);
45 sprintf(pathname, "%s\\%s", homedir, filename);
46 }
47 #else
48 if (homedir == NULL)
49 return (NULL);
50 pathname = (char *) calloc(strlen(homedir)+strlen(filename)+2,
51 sizeof(char));
52 if (pathname == NULL)
53 return (NULL);
54 sprintf(pathname, "%s/%s", homedir, filename);
55 #endif
56 return (pathname);
57 }
58
59 /*
60 * Find out where the help file is.
61 */
62 public char *
63 find_helpfile()
64 {
65 register char *helpfile;
66 #if __MSDOS__
67 extern char *searchpath();
68
69 /*
70 * Look in current directory.
71 */
72 if (access(HELPFILE,0) == 0)
73 return (HELPFILE);
74 /*
75 * Find the basename of HELPFILE,
76 * and look for it in each directory in the search path.
77 */
78 if ((helpfile = strrchr(HELPFILE, '\\')) == NULL)
79 helpfile = HELPFILE;
80 else
81 helpfile++;
82 return (save(searchpath(helpfile)));
83 #else
84 if ((helpfile = getenv("LESSHELP")) != NULL)
85 return (save(helpfile));
86 return (save(HELPFILE));
87 #endif
88 }
89
90 /*
91 * Expand a string, substituting any "%" with the current filename,
92 * and any "#" with the previous filename.
93 */
94 public char *
95 fexpand(s)
96 char *s;
97 {
98 register char *fr, *to;
99 register int n;
100 register char *e;
101
102 /*
103 * Make one pass to see how big a buffer we
104 * need to allocate for the expanded string.
105 */
106 n = 0;
107 for (fr = s; *fr != '\0'; fr++)
108 {
109 switch (*fr)
110 {
111 case '%':
112 n += strlen(get_filename(curr_ifile));
113 break;
114 case '#':
115 if (old_ifile == NULL_IFILE)
116 {
117 error("No previous file", NULL_PARG);
118 return (NULL);
119 }
120 n += strlen(get_filename(old_ifile));
121 break;
122 default:
123 n++;
124 break;
125 }
126 }
127
128 e = (char *) ecalloc(n+1, sizeof(char));
129
130 /*
131 * Now copy the string, expanding any "%" or "#".
132 */
133 to = e;
134 for (fr = s; *fr != '\0'; fr++)
135 {
136 switch (*fr)
137 {
138 case '%':
139 strcpy(to, get_filename(curr_ifile));
140 to += strlen(to);
141 break;
142 case '#':
143 strcpy(to, get_filename(old_ifile));
144 to += strlen(to);
145 break;
146 default:
147 *to++ = *fr;
148 break;
149 }
150 }
151 *to = '\0';
152 return (e);
153 }
154
155 /*
156 * Try to determine if a file is "binary".
157 * This is just a guess, and we need not try too hard to make it accurate.
158 */
159 int
160 bin_file(f)
161 int f;
162 {
163 int i;
164 int n;
165 char data[64];
166
167 n = read(f, data, sizeof(data));
168 for (i = 0; i < n; i++)
169 if (binary_char(data[i]))
170 return (1);
171 return (0);
172 }
173
174 /*
175 * Try to determine the size of a file by seeking to the end.
176 */
177 static POSITION
178 seek_filesize(f)
179 int f;
180 {
181 offset_t spos;
182
183 spos = lseek(f, (offset_t)0, 2);
184 if (spos == BAD_LSEEK)
185 return (NULL_POSITION);
186 return ((POSITION) spos);
187 }
188
189 /*
190 * Expand a filename, substituting any environment variables, etc.
191 */
192 #if GLOB
193
194 FILE *popen();
195
196 public char *
197 glob(filename)
198 char *filename;
199 {
200 FILE *f;
201 char *p;
202 int ch;
203 int len;
204 char *cmd;
205 char *gfilename;
206
207 filename = fexpand(filename);
208 if (filename == NULL)
209 return (NULL);
210
211 /*
212 * We get the shell to expand the filename for us by passing
213 * an "echo" command to the shell and reading its output.
214 */
215 p = getenv("SHELL");
216 if (p == NULL || *p == '\0')
217 {
218 /*
219 * Read the output of <echo filename>.
220 */
221 cmd = (char *) ecalloc(strlen(filename)+6, sizeof(char));
222 sprintf(cmd, "echo %s", filename);
223 } else
224 {
225 /*
226 * Read the output of <$SHELL -c "echo filename">.
227 */
228 cmd = (char *) ecalloc(strlen(p)+strlen(filename)+12, sizeof(char));
229 sprintf(cmd, "%s -c \"echo %s\"", p, filename);
230 }
231
232 f = popen(cmd, "r");
233 free(cmd);
234 if (f == NULL)
235 return (filename);
236 free(filename);
237
238 len = 100;
239 gfilename = (char *) ecalloc(len, sizeof(char));
240 for (p = gfilename; ; p++)
241 {
242 if ((ch = getc(f)) == '\n' || ch == EOF)
243 break;
244 if (p - gfilename >= len-1)
245 {
246 len *= 2;
247 *p = '\0';
248 p = (char *) ecalloc(len, sizeof(char));
249 strcpy(p, gfilename);
250 free(gfilename);
251 gfilename = p;
252 p = gfilename + strlen(gfilename);
253 }
254 *p = ch;
255 }
256 *p = '\0';
257 pclose(f);
258 if (*gfilename == '\0')
259 return (NULL);
260 return (gfilename);
261 }
262
263 #else
264
265 public char *
266 glob(filename)
267 char *filename;
268 {
269 return (fexpand(filename));
270 }
271
272 #endif
273
274
275 #if STAT
276
277 #include <sys/types.h>
278 #include <sys/stat.h>
279
280 /*
281 * Returns NULL if the file can be opened and
282 * is an ordinary file, otherwise an error message
283 * (if it cannot be opened or is a directory, etc.)
284 */
285 public char *
286 bad_file(filename)
287 char *filename;
288 {
289 register char *m;
290 struct stat statbuf;
291
292 if (stat(filename, &statbuf) < 0)
293 return (errno_message(filename));
294
295 if (force_open)
296 return (NULL);
297
298 if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
299 {
300 static char is_dir[] = " is a directory";
301 m = (char *) ecalloc(strlen(filename) + sizeof(is_dir),
302 sizeof(char));
303 strcpy(m, filename);
304 strcat(m, is_dir);
305 return (m);
306 }
307 if ((statbuf.st_mode & S_IFMT) != S_IFREG)
308 {
309 static char not_reg[] = " is not a regular file";
310 m = (char *) ecalloc(strlen(filename) + sizeof(not_reg),
311 sizeof(char));
312 strcpy(m, filename);
313 strcat(m, not_reg);
314 return (m);
315 }
316
317 return (NULL);
318 }
319
320 /*
321 * Return the size of a file, as cheaply as possible.
322 * In Unix, we can stat the file.
323 */
324 public POSITION
325 filesize(f)
326 int f;
327 {
328 struct stat statbuf;
329
330 if (fstat(f, &statbuf) < 0)
331 /*
332 * Can't stat; try seeking to the end.
333 */
334 return (seek_filesize(f));
335
336 return ((POSITION) statbuf.st_size);
337 }
338
339 #else
340
341 /*
342 * If we have no way to find out, just say the file is good.
343 */
344 public char *
345 bad_file(filename)
346 char *filename;
347 {
348 return (NULL);
349 }
350
351 /*
352 * We can find the file size by seeking.
353 */
354 public POSITION
355 filesize(f)
356 int f;
357 {
358 return (seek_filesize(f));
359 }
360
361 #endif