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