Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtsearchpath / dtsp / SearchPath.C
1 /* $XConsortium: SearchPath.C /main/3 1995/11/03 12:32:30 rswiston $ */
2 /*******************************************************************
3 **  (c) Copyright Hewlett-Packard Company, 1990, 1991, 1992, 1993.
4 **  All rights are reserved.  Copying or other reproduction of this
5 **  program except for archival purposes is prohibited without prior
6 **  written consent of Hewlett-Packard Company.
7 ********************************************************************
8 ****************************<+>*************************************/
9
10 #include "SearchPath.h"
11 #include "TTFile.h"
12 #include "Options.h"
13
14 extern Options * options;
15
16 /**********************************************************************
17  *
18  * SearchPath() - the constructor simply initializes the member data.
19  *
20  **********************************************************************/
21 SearchPath::SearchPath
22         (
23         CDEEnvironment *       user_,
24         const char *           envvar,
25         const char *           sep
26         ) : user(user_),
27             environment_var(envvar),
28             separator(sep),
29             parse_state(0),
30             final_search_path(""),
31             norm_search_path("")
32 {
33 }
34
35 /**********************************************************************
36  *
37  * ~SearchPath() - the destructor - nothing to do
38  *
39  **********************************************************************/
40 SearchPath::~SearchPath()
41 {
42 }
43
44
45 /**********************************************************************
46  *
47  * constructPath - this member function takes a host and a path and
48  *                 either calls the Tooltalk filemapping library or
49  *                 constructs it in the standard fashion.
50  *
51  **********************************************************************/
52 CString SearchPath::ConstructPath
53         (
54         const CString & path,
55         const CString * host,
56         unsigned char
57         )
58 {
59 CString final_path;
60
61     if (host) {
62         if (options->doingTooltalk()) {
63             TTFile * file;
64             Try {
65                 file = new TTFile(*host,path);
66                 if (!file->ttFileOpFailed())
67                     final_path = *file;
68                 if (options->removeAutoMountPoint()) {
69                     if (final_path.contains(options->getAutoMountPoint(),
70                                                 "","/"))
71                         final_path.replace(options->getAutoMountPoint(),"");
72                 }
73             }
74             Catch (TTFile::TT_Exception *, file) {
75                 final_path = user->OS()->MountPoint() + *host + path;
76             }
77             delete file;
78         }
79         else 
80             final_path = user->OS()->MountPoint() + *host + path;
81     }
82     else
83         final_path = path;
84
85     return final_path;
86 }
87
88 /*************************************************************************
89  *  AssembleString()
90  *
91  *         Given a series of string elements one at a time--either a host
92  *         or a path, in any order--tokenize them, and create
93  *         a normalized path of the form:
94  *
95  *         "host:/path,host:/path"
96  *
97  *         Return this normalized path in $RETURN_STRING.
98  *
99  *************************************************************************/
100 void SearchPath::AssembleString
101         (
102         const CString & path_element
103         ) 
104 {
105     if (parse_state == 1 && norm_search_path.length())
106         if (norm_search_path[norm_search_path.length()-1] != ',')
107             norm_search_path += ",";
108
109     if (path_element.length() == 0) {
110
111         if (parse_state == 2) {
112             CString path(save_host + ":" + user->SysAdmConfig());
113             if (!norm_search_path.contains(path, ",", ","))
114                 norm_search_path += path;
115             parse_state = 1;
116         }
117     }     
118     else if (path_element[0] == '/') {
119
120         // B -- a path
121
122         if (parse_state == 1) {
123             CString path(user->OS()->LocalHost() + ":" + path_element);
124             if (!norm_search_path.contains(path, ",", ","))
125                 norm_search_path += path;
126             parse_state = 1;
127         }
128         else if (parse_state == 2) {
129             CString path(save_host + ":" + path_element);
130             if (!norm_search_path.contains(path, ",", ","))
131                 norm_search_path += path;
132             parse_state = 1;
133         }
134     }
135
136     else if (path_element[0] == '>') {
137
138         // terminator--write out the saved host and default path.
139
140         CString path(save_host + ":" + user->SysAdmConfig());
141         if (!norm_search_path.contains(path, ",", ","))
142             norm_search_path += path;
143         parse_state = 3;
144     }
145
146     else {
147
148         //  A -- a host
149
150         if (parse_state == 1) {
151             save_host = path_element;
152             parse_state = 2;
153         }
154
155         else if (parse_state == 2) {
156             CString path(save_host + ":" + user->SysAdmConfig());
157             if (!norm_search_path.contains(path, ",", ","))
158                 norm_search_path += path;
159             save_host = path_element;
160             parse_state = 2;
161         }
162     }
163 }
164
165 /*****************************************************************
166  *  NormalizePath()
167  * 
168  *  This function takes a complete string and calls the helper
169  *  function AssembleString() to build a normalized path.
170  *
171  *****************************************************************/
172 void SearchPath::NormalizePath()
173 {
174     parse_state = 1;
175
176     if (search_path.length()) {
177         CTokenizedString subpath(search_path,":,");
178         CString dirname = subpath.next();
179         while (!subpath.Finished()) {
180             AssembleString (dirname);
181             dirname = subpath.next();
182         }
183     }
184
185     // flush the buffer
186
187     if (parse_state == 2)
188         AssembleString(">");
189     else
190         return;
191 }
192
193
194 /*********************************************************************
195  *  AddToPath()
196  *
197  *     Take the second parameter (if it exists), and add the
198  *     first parameter (always assumed) to its end separated by the
199  *     specified separator
200  *********************************************************************/
201
202 void SearchPath::AddToPath
203         (
204         const CString & path
205         )
206 {
207     if (!final_search_path.isNull()) {
208         if (!final_search_path.contains (path, Separator().data(),
209                                                Separator().data())) {
210             final_search_path += Separator();
211             final_search_path += path;
212         }
213     }
214     else
215         final_search_path += path;
216 }
217
218 /*********************************************************************
219  *  TraversePath()
220  *
221  *     Parse a given search path, using comma (,) and colon (:) as
222  *     delimiters.  Pass the normalized path to the virtual MakePath.
223  *     function.
224  *
225  *     N.B.  We assume that we have a normalized path at this point.
226  *
227  *********************************************************************/
228 void SearchPath::TraversePath()
229 {
230     if (!norm_search_path.isNull()) {
231         CTokenizedString subpath(norm_search_path,",");
232         CString dirname = subpath.next();
233         while (!dirname.isNull()) {
234             MakePath (dirname);
235             dirname = subpath.next();
236         }
237     }
238 }
239
240
241 /*********************************************************************
242  *  AddPredefinedPath()
243  *
244  *    If it is possible that an environment variable can be set
245  *    before dtsearchpath is run, check for its existence, and if it
246  *    exists, append it to the searchpath.
247  *
248  *********************************************************************/
249 void SearchPath::AddPredefinedPath()
250 {
251     CString envVar_in(environment_var);
252     envVar_in += "SEARCHPATH";
253     CString envVar_out = user->OS()->getEnvironmentVariable(envVar_in.data());
254     if (!envVar_out.isNull()) {
255         CString specified_path(envVar_out);
256         if (!specified_path.contains(search_path))
257             search_path += Separator() + specified_path;
258         else
259             search_path = specified_path;
260     }
261 }
262
263
264 /*********************************************************************
265  *  validSearchPath()
266  *
267  *    This member function verifies that the path in question is a
268  *    standard CDE location, i.e. /etc/dt/appconfig or /usr/dt/appconfig
269  *    so that the appropriate massaging can take place.
270  *
271  *********************************************************************/
272 int SearchPath::validSearchPath
273         (
274         const CString & st
275         ) const
276 {
277     if (st == user->SysAdmConfig())
278         return 1;
279
280     if (st == user->FactoryInstall())
281         return 1;
282
283     // If this is an APP-specified path, it also needs to be massaged.
284
285     // The elements in the APP paths may be host:/path so use the 
286     // colon as the leader.
287
288     if (user->DTAPPSP() && 
289         user->DTAPPSP()->contains (st, ":", separator.data()))
290         return 1;
291
292     if (user->DTUSERAPPSP() && 
293         user->DTUSERAPPSP()->contains (st, ":", separator.data()))
294         return 1;
295
296     // they may also be there by themselves: "host:,/path" so use the
297     // comma as the leader.
298
299     if (user->DTAPPSP() && 
300         user->DTAPPSP()->contains (st, ",", separator.data()))
301         return 1;
302
303     if (user->DTUSERAPPSP() && 
304         user->DTUSERAPPSP()->contains (st, ",", separator.data()))
305         return 1;
306
307     return 0;
308 }
309
310 /*****************************************************************
311  *  ExportPath()
312  *
313  *         Export the variable value to the rest of the session.
314  *
315  *****************************************************************/
316 void SearchPath::ExportPath()
317 {
318     CString env(environment_var);
319     env += "SEARCHPATH";
320
321     user->OS()->shell()->putToEnv(env, final_search_path.data());
322 }
323
324
325 /*****************************************************************
326  *  Print()
327  *
328  *    In the absence of iostreams, use printf to output information
329  *
330  *****************************************************************/
331 void SearchPath::Print()
332 {
333     printf("%sSEARCHPATH:\n", GetEnvVar());
334     CString sp(GetSearchPath());
335     if (!sp.isNull()) {
336         CTokenizedString path (sp,Separator().data());
337         CString subpath = path.next();
338         while (!subpath.isNull()) {
339             printf("\t%s\n",subpath.data());
340             subpath = path.next();
341         }
342         printf("\n");
343     }
344 }
345
346 /****************************************************************
347  *  PrettyPrint()
348  *
349  *    Print the list such that each entry occupys its own line
350  *
351  ****************************************************************/
352
353 void SearchPath::PrettyPrint
354         (
355         ostream & os
356         ) const
357 {
358     CTokenizedString path (GetSearchPath(), Separator().data());
359     CString subpath = path.next();
360     while (!subpath.isNull()) {
361         os << "        " << subpath << endl;
362         subpath = path.next();
363     }
364     os << endl;
365 }
366
367
368 /****************************************************************
369  *  operator<<()
370  *
371  *    Allow SearchPath types to be output using iostreams.
372  *
373  ****************************************************************/
374
375 ostream & operator<< 
376         (
377         ostream & os, 
378         const SearchPath & sp
379         )
380 {
381     os << sp.GetEnvVar() << "SEARCHPATH:" << endl;
382     sp.PrettyPrint(os);
383     return os;
384 }
385