1 /*
2    Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
3 
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License, version 2.0,
7    as published by the Free Software Foundation.
8 
9    This program is also distributed with certain software (including
10    but not limited to OpenSSL) that is licensed under separate terms,
11    as designated in a particular file or component or in included license
12    documentation.  The authors of MySQL hereby grant you an additional
13    permission to link the program and your derivative works with the
14    separately licensed software that they have included with MySQL.
15 
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License, version 2.0, for more details.
20 
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24  */
25 
26 
27 #include <NDBT_Find.hpp>
28 #include <NdbEnv.h>
29 
30 #ifndef _WIN32
31 #define PATH_SEPARATOR ":"
32 #else
33 #define PATH_SEPARATOR ";"
34 #endif
35 
36 void
NDBT_find_binary_from_path(BaseString & name,const char * binary_name,const char * _path)37 NDBT_find_binary_from_path(BaseString& name,
38                            const char* binary_name,
39                            const char * _path)
40 {
41   char * copy = strdup(_path);
42 
43   // Loop the list of paths and see if the binary exists
44   char *n = copy;
45   while (n != NULL)
46   {
47     char * s = n;
48     n = strstr(s, PATH_SEPARATOR);
49     if (n != NULL)
50     {
51       * n = 0;
52       n += strlen(PATH_SEPARATOR);
53     }
54     BaseString path;
55     path.assfmt("%s/%s", s, binary_name);
56     if (access(path.c_str(), F_OK) == 0)
57     {
58       // Sucess, found the binary. Convert path to absolute and return it
59       char realpath_buf[PATH_MAX];
60 #ifndef _WIN32
61       if (realpath(path.c_str(), realpath_buf) == NULL)
62       {
63         fprintf(stderr, "Could not convert '%s' to realpath\n", path.c_str());
64         abort();
65       }
66 #else
67       int ret= GetFullPathName(path.c_str(), sizeof(realpath_buf),
68                                realpath_buf, NULL);
69       if (ret == 0 || ret >= sizeof(realpath_buf))
70       {
71         fprintf(stderr, "Could not convert '%s' with GetFullPathName\n",
72                 path.c_str());
73         abort();
74       }
75 #endif
76 
77       name.assign(realpath_buf);
78       free(copy);
79       printf("found %s\n", name.c_str());
80       return;
81     }
82   }
83 
84   // Failed to find the binary in any of the supplied paths
85   fprintf(stderr, "Could not find '%s' in '%s'\n",
86           binary_name, _path);
87   free(copy);
88   abort();
89 }
90 
91 void
NDBT_find_binary(BaseString & name,const char * binary_name,const char * first_path,...)92 NDBT_find_binary(BaseString& name, const char* binary_name,
93                  const char* first_path, ...)
94 {
95   BaseString path(first_path);
96 
97   // Push all the different paths to a list
98   const char* str = first_path;
99   va_list args;
100   va_start(args, first_path);
101   while ((str = va_arg(args, const char*)) != NULL)
102   {
103     path.appfmt("%s%s", PATH_SEPARATOR, str);
104   }
105   va_end(args);
106 
107   NDBT_find_binary_from_path(name, binary_name, path.c_str());
108 }
109 
110 extern const char * my_progname;
111 
112 void
NDBT_find_ndb_mgmd(BaseString & path)113 NDBT_find_ndb_mgmd(BaseString& path)
114 {
115   char pathbuf[1024];
116 
117   /**
118    * 1) avoid using dirname/basename since they are not around on WIN
119    * 2) define single character SEP to be able to use strrchr
120    */
121   BaseString copy(my_progname);
122 #ifdef NDB_WIN
123   char SEP = '\\';
124 #else
125   char SEP = '/';
126 #endif
127   char * basename = const_cast<char*>(strrchr(copy.c_str(), SEP));
128   if (basename == 0)
129   {
130     /**
131      * No directory part in argv[0]
132      *   => found in $PATH => search for ndb_mgmd in $PATH
133      */
134     NDBT_find_binary(path,
135                      "ndb_mgmd",
136                      NdbEnv_GetEnv("PATH", pathbuf, sizeof(pathbuf)),
137                      NULL);
138   }
139   else
140   {
141     /**
142      * Directory part in argv[0] (e.g storage/ndb/test/ndbapi/testMgmd)
143      *   => don't add $PATH
144      *   => search in relative places relative argv[0]
145      */
146     * basename = 0;
147     const char * places[] = {
148       "../../src/mgmsrv",
149       "../storage/ndb/src/mgmsrv",
150       "../libexec",
151       "../sbin",
152       "../bin",
153       0
154     };
155     BaseString searchpath = "";
156     for (int i = 0; places[i] != 0; i++) {
157       searchpath.appfmt("%s%s%c%s",
158                         (i == 0 ? "" : PATH_SEPARATOR),
159                         copy.c_str(),
160                         SEP,
161                         places[i]);
162     }
163     NDBT_find_binary(path,
164                      "ndb_mgmd",
165                      searchpath.c_str(),
166                      NULL);
167   }
168 }
169 
170