00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include "sbuild-error.h"
00023 #include "sbuild-util.h"
00024
00025 #include <sys/types.h>
00026 #include <sys/stat.h>
00027 #include <unistd.h>
00028
00029 using namespace sbuild;
00030
00031 namespace
00032 {
00033
00041 std::string remove_duplicates (std::string const& str,
00042 char dup)
00043 {
00044 std::string ret;
00045
00046 for (std::string::size_type pos = 0;
00047 pos < str.length();
00048 ++pos)
00049 {
00050 ret += str[pos];
00051 if (str[pos] == dup)
00052 {
00053 while (pos + 1 < str.length() &&
00054 str[pos + 1] == dup)
00055 ++pos;
00056 }
00057 }
00058
00059 return ret;
00060 }
00061
00062 }
00063
00064 std::string
00065 sbuild::basename (std::string name,
00066 char separator)
00067 {
00068
00069 std::string::size_type cur = name.length();
00070 while (cur - 1 != 0 && name[cur - 1] == separator)
00071 --cur;
00072 name.resize(cur);
00073
00074
00075 std::string::size_type pos = name.rfind(separator);
00076
00077 std::string ret;
00078 if (pos == std::string::npos)
00079 ret = name;
00080 else if (pos == 0 && name.length() == 1 && name[0] == separator)
00081 ret = separator;
00082 else
00083 ret = name.substr(pos + 1);
00084
00085 return remove_duplicates(ret, separator);
00086 }
00087
00088 std::string
00089 sbuild::dirname (std::string name,
00090 char separator)
00091 {
00092
00093 std::string::size_type cur = name.length();
00094 while (cur - 1 != 0 && name[cur - 1] == separator)
00095 --cur;
00096 name.resize(cur);
00097
00098
00099 std::string::size_type pos = name.rfind(separator);
00100
00101 std::string ret;
00102 if (pos == std::string::npos)
00103 ret = ".";
00104 else if (pos == 0)
00105 ret = separator;
00106 else
00107 ret = name.substr(0, pos);
00108
00109 return remove_duplicates(ret, separator);
00110 }
00111
00112 std::string
00113 sbuild::normalname (std::string name,
00114 char separator)
00115 {
00116
00117 std::string::size_type cur = name.length();
00118 while (cur - 1 != 0 && name[cur - 1] == separator)
00119 --cur;
00120 name.resize(cur);
00121
00122 return remove_duplicates(name, separator);
00123 }
00124
00125 bool
00126 sbuild::is_absname (std::string const& name)
00127 {
00128 if (name.empty() || name[0] != '/')
00129 return false;
00130 else
00131 return true;
00132 }
00133
00134 std::string
00135 sbuild::string_list_to_string (sbuild::string_list const& list,
00136 std::string const& separator)
00137 {
00138 std::string ret;
00139
00140 for (string_list::const_iterator cur = list.begin();
00141 cur != list.end();
00142 ++cur)
00143 {
00144 ret += *cur;
00145 if (cur + 1 != list.end())
00146 ret += separator;
00147 }
00148
00149 return ret;
00150 }
00151
00152 string_list
00153 sbuild::split_string (std::string const& value,
00154 std::string const& separator)
00155 {
00156 string_list ret;
00157
00158
00159 std::string::size_type last_pos =
00160 value.find_first_not_of(separator, 0);
00161
00162 std::string::size_type pos = value.find_first_of(separator, last_pos);
00163
00164 while (pos !=std::string::npos || last_pos != std::string::npos)
00165 {
00166
00167 ret.push_back(value.substr(last_pos, pos - last_pos));
00168
00169 last_pos = value.find_first_not_of(separator, pos);
00170 pos = value.find_first_of(separator, last_pos);
00171 }
00172
00173 return ret;
00174 }
00175
00176 std::wstring
00177 sbuild::widen_string (std::string const& str,
00178 std::locale locale)
00179 {
00180 typedef std::codecvt<wchar_t, char, mbstate_t> codecvt_type;
00181 codecvt_type const& cvt = std::use_facet<codecvt_type>(locale);
00182 mbstate_t state;
00183 const char *cbegin = str.data(), *cend = str.data() + str.size(), *cnext;
00184 wchar_t *wcnext;
00185 wchar_t wcbuf[80];
00186 std::wstring ret;
00187
00188 std::memset(&state, 0, sizeof(mbstate_t));
00189
00190 while (1)
00191 {
00192 std::codecvt_base::result res =
00193 cvt.in(state,
00194 cbegin, cend, cnext,
00195 wcbuf, wcbuf + (sizeof(wcbuf) / sizeof(wcbuf[0])), wcnext);
00196
00197 if (res == std::codecvt_base::ok || res == std::codecvt_base::partial)
00198 {
00199 ret += std::wstring(wcbuf, wcnext);
00200 if (cend == cnext)
00201 break;
00202 }
00203 else if (res == std::codecvt_base::noconv)
00204 {
00205 ret += std::wstring(cbegin, cend);
00206 break;
00207 }
00208 else if (res == std::codecvt_base::error)
00209 {
00210 throw std::runtime_error
00211 ("A character set conversion failed. Please report this bug.");
00212 break;
00213 }
00214 else
00215 break;
00216
00217 cbegin = cnext;
00218 }
00219
00220 return ret;
00221 }
00222
00223 std::string
00224 sbuild::narrow_string (std::wstring const& str,
00225 std::locale locale)
00226 {
00227 typedef std::codecvt<wchar_t, char, mbstate_t> codecvt_type;
00228 codecvt_type const& cvt = std::use_facet<codecvt_type>(locale);
00229 mbstate_t state;
00230 const wchar_t *wcbegin = str.data(), *wcend = str.data() + str.size(), *wcnext;
00231 char *cnext;
00232 char cbuf[80];
00233 std::string ret;
00234
00235 std::memset(&state, 0, sizeof(mbstate_t));
00236
00237 while (1)
00238 {
00239 std::codecvt_base::result res =
00240 cvt.out(state,
00241 wcbegin, wcend, wcnext,
00242 cbuf, cbuf + (sizeof(cbuf) / sizeof(cbuf[0])), cnext);
00243
00244 if (res == std::codecvt_base::ok || res == std::codecvt_base::partial)
00245 {
00246 ret += std::string(cbuf, cnext);
00247 if (wcend == wcnext)
00248 break;
00249 }
00250 else if (res == std::codecvt_base::noconv)
00251 {
00252 ret += std::string(wcbegin, wcend);
00253 break;
00254 }
00255 else if (res == std::codecvt_base::error)
00256 {
00257 throw std::runtime_error
00258 ("A character set conversion failed. Please report this bug.");
00259 break;
00260 }
00261 else
00262 break;
00263
00264 wcbegin = wcnext;
00265 }
00266
00267 return ret;
00268 }
00269
00270 std::string
00271 sbuild::find_program_in_path (std::string const& program,
00272 std::string const& path,
00273 std::string const& prefix)
00274 {
00275 if (program.find_first_of('/') != std::string::npos)
00276 return program;
00277
00278 string_list dirs = split_string(path, std::string(1, ':'));
00279
00280 for (string_list::const_iterator dir = dirs.begin();
00281 dir != dirs.end();
00282 ++dir)
00283 {
00284 std::string realname = *dir + '/' + program;
00285 std::string absname;
00286 if (prefix.length() > 0)
00287 {
00288 absname = prefix;
00289 if (dir->length() > 0 && (*dir)[0] != '/')
00290 absname += '/';
00291 }
00292 absname += realname;
00293
00294 struct stat statbuf;
00295 if (stat(absname.c_str(), &statbuf) == 0)
00296 {
00297 if (S_ISREG(statbuf.st_mode) &&
00298 access (absname.c_str(), X_OK) == 0)
00299 return realname;
00300 }
00301 }
00302
00303 return "";
00304 }
00305
00306 char **
00307 sbuild::string_list_to_strv (string_list const& str)
00308 {
00309 char **ret = new char *[str.size() + 1];
00310
00311 for (string_list::size_type i = 0;
00312 i < str.size();
00313 ++i)
00314 {
00315 ret[i] = new char[str[i].length() + 1];
00316 std::strcpy(ret[i], str[i].c_str());
00317 }
00318 ret[str.size()] = 0;
00319
00320 return ret;
00321 }
00322
00323
00324 void
00325 sbuild::strv_delete (char **strv)
00326 {
00327 for (char **pos = strv; pos != 0 && *pos != 0; ++pos)
00328 delete *pos;
00329 delete[] strv;
00330 }
00331
00332 int
00333 sbuild::exec (std::string const& file,
00334 string_list const& command,
00335 environment const& env)
00336 {
00337 char **argv = string_list_to_strv(command);
00338 char **envp = env.get_strv();
00339 int status;
00340
00341 if ((status = execve(file.c_str(), argv, envp)) != 0)
00342 {
00343 strv_delete(argv);
00344 strv_delete(envp);
00345 }
00346
00347 return status;
00348 }