* src/libs/libgroff/tmpfile.cpp [__MSDOS__, _Win32]
[s-roff.git] / src / libs / libgroff / searchpath.cpp
blobce08cdf23398c3e91f932a3c6a41eebfba448050
1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2003
3 Free Software Foundation, Inc.
4 Written by James Clark (jjc@jclark.com)
6 This file is part of groff.
8 groff is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
13 groff is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License along
19 with groff; see the file COPYING. If not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 #include "lib.h"
24 #include <stdlib.h>
25 #include <assert.h>
26 #include <errno.h>
28 #include "searchpath.h"
29 #include "nonposix.h"
31 search_path::search_path(const char *envvar, const char *standard,
32 int add_home, int add_current)
34 char *home = 0;
35 if (add_home)
36 home = getenv("HOME");
37 char *e = 0;
38 if (envvar)
39 e = getenv(envvar);
40 dirs = new char[((e && *e) ? strlen(e) + 1 : 0)
41 + (add_current ? 1 + 1 : 0)
42 + ((home && *home) ? strlen(home) + 1 : 0)
43 + ((standard && *standard) ? strlen(standard) : 0)
44 + 1];
45 *dirs = '\0';
46 if (e && *e) {
47 strcat(dirs, e);
48 strcat(dirs, PATH_SEP);
50 if (add_current) {
51 strcat(dirs, ".");
52 strcat(dirs, PATH_SEP);
54 if (home && *home) {
55 strcat(dirs, home);
56 strcat(dirs, PATH_SEP);
58 if (standard && *standard)
59 strcat(dirs, standard);
60 init_len = strlen(dirs);
63 search_path::~search_path()
65 // dirs is always allocated
66 a_delete dirs;
69 void search_path::command_line_dir(const char *s)
71 char *old = dirs;
72 unsigned old_len = strlen(old);
73 unsigned slen = strlen(s);
74 dirs = new char[old_len + 1 + slen + 1];
75 memcpy(dirs, old, old_len - init_len);
76 char *p = dirs;
77 p += old_len - init_len;
78 if (init_len == 0)
79 *p++ = PATH_SEP[0];
80 memcpy(p, s, slen);
81 p += slen;
82 if (init_len > 0) {
83 *p++ = PATH_SEP[0];
84 memcpy(p, old + old_len - init_len, init_len);
85 p += init_len;
87 *p++ = '\0';
88 a_delete old;
91 FILE *search_path::open_file(const char *name, char **pathp)
93 assert(name != 0);
94 if (IS_ABSOLUTE(name) || *dirs == '\0') {
95 FILE *fp = fopen(name, "r");
96 if (fp) {
97 if (pathp)
98 *pathp = strsave(name);
99 return fp;
101 else
102 return 0;
104 unsigned namelen = strlen(name);
105 char *p = dirs;
106 for (;;) {
107 char *end = strchr(p, PATH_SEP[0]);
108 if (!end)
109 end = strchr(p, '\0');
110 int need_slash = end > p && strchr(DIR_SEPS, end[-1]) == 0;
111 char *path = new char[(end - p) + need_slash + namelen + 1];
112 memcpy(path, p, end - p);
113 if (need_slash)
114 path[end - p] = '/';
115 strcpy(path + (end - p) + need_slash, name);
116 #if 0
117 fprintf(stderr, "trying `%s'\n", path);
118 #endif
119 FILE *fp = fopen(path, "r");
120 if (fp) {
121 if (pathp)
122 *pathp = path;
123 else
124 a_delete path;
125 return fp;
127 a_delete path;
128 if (*end == '\0')
129 break;
130 p = end + 1;
132 return 0;
135 FILE *search_path::open_file_cautious(const char *name, char **pathp,
136 const char *mode)
138 if (!mode)
139 mode = "r";
140 bool reading = (strchr(mode, 'r') != 0);
141 if (name == 0 || strcmp(name, "-") == 0) {
142 if (pathp)
143 *pathp = strsave(reading ? "stdin" : "stdout");
144 return (reading ? stdin : stdout);
146 if (!reading || IS_ABSOLUTE(name) || *dirs == '\0') {
147 FILE *fp = fopen(name, mode);
148 if (fp) {
149 if (pathp)
150 *pathp = strsave(name);
151 return fp;
153 else
154 return 0;
156 unsigned namelen = strlen(name);
157 char *p = dirs;
158 for (;;) {
159 char *end = strchr(p, PATH_SEP[0]);
160 if (!end)
161 end = strchr(p, '\0');
162 int need_slash = end > p && strchr(DIR_SEPS, end[-1]) == 0;
163 char *path = new char[(end - p) + need_slash + namelen + 1];
164 memcpy(path, p, end - p);
165 if (need_slash)
166 path[end - p] = '/';
167 strcpy(path + (end - p) + need_slash, name);
168 #if 0
169 fprintf(stderr, "trying `%s'\n", path);
170 #endif
171 FILE *fp = fopen(path, mode);
172 if (fp) {
173 if (pathp)
174 *pathp = path;
175 else
176 a_delete path;
177 return fp;
179 int err = errno;
180 a_delete path;
181 if (err != ENOENT)
183 errno = err;
184 return 0;
186 if (*end == '\0')
187 break;
188 p = end + 1;
190 errno = ENOENT;
191 return 0;