ns-3 Direct Code Execution
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
exec-utils.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 INRIA
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 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Frederic Urbani <frederic.urbani@inria.fr>
19  *
20  */
21 #include <iostream>
22 #include <sstream>
23 #include <string.h>
24 #include <vector>
25 #include "exec-utils.h"
26 #include "utils.h"
27 #include "dce-manager.h"
28 #include "process.h"
29 #include "dce-unistd.h"
30 #include "errno.h"
31 
32 namespace ns3 {
33 
35 {
36  uid_t uid;
37  gid_t gid;
38  int *errNo;
39 };
40 
41 bool CanonizePath (std::string path, bool ChRootProtected, std::ostringstream &result)
42 {
43  std::vector <std::string> profs;
44  std::ostringstream cur;
45  int level = 0;
46  const char *crsr = path.c_str ();
47  int state = 0;
48  bool SlashStart = ('/' == *crsr);
49 
50  do
51  {
52  switch (state)
53  {
54  case 0:
55  {
56  switch (*crsr)
57  {
58  case '.':
59  {
60  state = 1;
61  }
62  break;
63  case 0:
64  case '/':
65  break;
66  default:
67  {
68  cur << *crsr;
69  state = 2;
70  }
71  break;
72  }
73  }
74  break;
75  case 1: // .
76  {
77  switch (*crsr)
78  {
79  case '.':
80  {
81  state = 3;
82  }
83  break;
84  case 0:
85  case '/':
86  {
87  state = 0;
88  }
89  break;
90  default:
91  {
92  cur << '.' << *crsr;
93  state = 2;
94  }
95  break;
96  }
97  }
98  break;
99  case 2: // other
100  {
101  if (('/' == *crsr)||(!*crsr))
102  {
103  state = 0;
104  level++;
105  std::string e = cur.str ();
106  profs.push_back (e);
107  cur.clear ();
108  cur.str ("");
109  }
110  else
111  {
112  cur << *crsr;
113  }
114  }
115  break;
116  case 3: // ..
117  {
118  switch (*crsr)
119  {
120  case 0:
121  case '/':
122  {
123  level--;
124  if (ChRootProtected && !SlashStart && (level < 0))
125  {
126  return false;
127  }
128  if (level >= 0)
129  {
130  profs.pop_back ();
131  }
132  else
133  {
134  profs.push_back ("..");
135  }
136  state = 0;
137  }
138  break;
139  default:
140  {
141  cur << '.' << '.' << *crsr;
142  state = 2;
143  }
144  break;
145  }
146  }
147  break;
148  default:
149  return false;
150  }
151  if (*crsr)
152  {
153  crsr++;
154  }
155  else
156  {
157  break;
158  }
159  }
160  while (true);
161 
162  bool first = true;
163  if (profs.size () > 0)
164  {
165  for (std::vector <std::string> :: iterator i = profs.begin () ; i != profs.end () ; ++i)
166  {
167  if (!first || SlashStart)
168  {
169  result << '/' ;
170  }
171  first = false;
172  result << *i ;
173  }
174  }
175  else
176  {
177  if (SlashStart)
178  {
179  result << '/' ;
180  }
181  else
182  {
183  result << '.' ;
184  }
185  }
186 
187  return true;
188 }
189 SearchPath::SearchPath (std::string basepath, std::string paths, bool virt) : m_basePath (basepath),
190  m_virtual (virt)
191 {
192  bool prot = (m_basePath.length () > 0);
193  std::list<std::string> p = Split (paths, ":");
194  for (std::list<std::string>::const_iterator i = p.begin (); i != p.end (); i++)
195  {
196  std::ostringstream cano;
197  if (CanonizePath (*i, prot, cano))
198  {
199  std::string e = cano.str ();
200  if (e.length () > 0)
201  {
202  m_paths.push_back (e);
203  }
204  }
205  }
206 }
207 std::string
208 SearchPath::SeekFile (std::string file, std::string cwd, void *userData, bool (*checker)(std::string, void*))
209 {
210  for (std::vector <std::string>::const_iterator i = m_paths.begin (); i != m_paths.end (); ++i)
211  {
212  std::string p = *i;
213  std::string pp;
214  if (*p.c_str () == '/')
215  {
216  if (m_virtual)
217  {
218  if (p.length () > 0)
219  {
220  pp = m_basePath + "/" + p + "/" + file;
221  }
222  else
223  {
224  pp = m_basePath + "/" + file;
225  }
226  }
227  else
228  {
229  pp = p + "/" + file;
230  }
231  }
232  else
233  {
234  if (m_virtual)
235  {
236  if ((cwd.length () > 0) && (p.length () > 0))
237  {
238  pp = m_basePath + "/" + cwd + "/" + p + "/" + file;
239  }
240  else
241  if (cwd.length () > 0)
242  {
243  pp = m_basePath + "/" + cwd + "/" + file;
244  }
245  else
246  {
247  pp = m_basePath + "/" + file;
248  }
249  }
250  else
251  {
252  pp = p + "/" + file;
253  }
254  }
255  std::ostringstream cano;
256  CanonizePath (pp, false, cano);
257  pp = cano.str ();
258  if ((pp.length () > 0) && checker (pp, userData))
259  {
260  return pp;
261  }
262  }
263  return "";
264 }
265 std::string
266 SearchAbsoluteFile (std::string file, std::string vroot, std::string altRoots, void *userData,
267  bool (*checker)(std::string, void*))
268 {
269  SearchPath p1 (vroot, ".", true);
270  std::string res = p1.SeekFile (file, "", userData, checker);
271  if (res.length () > 0)
272  {
273  return res;
274  }
275  else
276  {
277  SearchPath p2 ("", altRoots, false);
278  return p2.SeekFile (file, "", userData, checker);
279  }
280 }
281 std::string
282 SearchRelativeFile (std::string file, std::string vroot, std::string cwd,
283  void *userData, bool (*checker)(std::string, void*))
284 {
285  SearchPath p1 (vroot, cwd, true);
286  return p1.SeekFile (file, "", userData, checker);
287 }
288 std::string
289 SearchSimpleFile (std::string file,
290  std::string vroot,
291  std::string vpath,
292  std::string cwd,
293  std::string dcepath,
294  void *userData,
295  bool (*checker)(std::string, void*))
296 {
297  SearchPath p1 (vroot, vpath, true);
298  std::string res = p1.SeekFile (file, cwd, userData, checker);
299  if (res.length () > 0)
300  {
301  return res;
302  }
303  else
304  {
305  SearchPath p2 ("", dcepath, false);
306  return p2.SeekFile (file,"", userData, checker);
307  }
308 }
309 std::string
310 SearchFile (std::string file,
311  std::string vroot,
312  std::string vpath,
313  std::string dcepath,
314  std::string cwd,
315  std::string altRoots,
316  void *userData,
317  bool (*checker)(std::string, void*))
318 {
319  if (*file.c_str () == '/')
320  {
321  return SearchAbsoluteFile (file, vroot, altRoots, userData, checker);
322  }
323  int idx = file.find ('/',0);
324  if (idx >= 0)
325  {
326  return SearchRelativeFile (file, vroot, cwd, userData, checker);
327  }
328  return SearchSimpleFile (file, vroot, vpath, cwd, dcepath, userData, checker);
329 }
330 std::string
331 SearchFile (std::string file,
332  std::string vroot,
333  std::string cwd,
334  std::string altRoots,
335  void *userData,
336  bool (*checker)(std::string, void*))
337 {
338  if (*file.c_str () == '/')
339  {
340  return SearchAbsoluteFile (file, vroot, altRoots, userData, checker);
341  }
342  return SearchRelativeFile (file, vroot, cwd, userData, checker);
343 }
344 bool
345 CheckFileExe (std::string file, void *params)
346 {
347  struct stat st;
348  struct ExeCriteria *criteria = (struct ExeCriteria *) params;
349 
350  if (0 != ::stat (file.c_str (), &st))
351  {
352  return false;
353  }
354  if (criteria)
355  {
356  uid_t uid = criteria->uid;
357  gid_t gid = criteria->gid;
358  if (((uid) && CheckExeMode (&st, uid, gid)) || (!uid))
359  {
360  return true;
361  }
362  if (criteria->errNo)
363  {
364  *criteria->errNo = ENOEXEC;
365  }
366  return false;
367  }
368  return true;
369 }
370 std::string
371 SearchExecFile (std::string file, std::string vpath, uid_t uid, gid_t gid, int *errNo)
372 {
373  std::string vroot = UtilsGetRealFilePath ("/");
374  Thread *current = Current ();
375  DceManager *manager = current->process->manager;
376  std::string dcepath = "";
377  std::string cwd = dce_get_current_dir_name ();
378  std::string altRoots = "";
379  char *c = getenv ("DCE_PATH");
380  struct ExeCriteria userData;
381  if (errNo)
382  {
383  *errNo = ENOENT;
384  }
385  if (vpath.length () == 0)
386  {
387  if (manager->GetVirtualPath ().length () > 0)
388  {
389  vpath = manager->GetVirtualPath ();
390  }
391  }
392  else
393  {
394  if (manager->GetVirtualPath ().length () > 0)
395  {
396  vpath = vpath + ':' + manager->GetVirtualPath ();
397  }
398  }
399  if (c)
400  {
401  dcepath = c;
402  }
403  c = getenv ("DCE_ROOT");
404  if (c)
405  {
406  altRoots = c;
407  }
408  userData.uid = uid;
409  userData.gid = gid;
410  userData.errNo = errNo;
411 
412  return SearchFile (file, vroot, vpath, dcepath, cwd, altRoots, &userData, CheckFileExe);
413 }
414 std::string
415 SearchExecFile (std::string file, uid_t uid, gid_t gid, int *errNo)
416 {
417  std::string vroot = UtilsGetRealFilePath ("/");
418  std::string cwd = dce_get_current_dir_name ();
419  std::string altRoots = "";
420  struct ExeCriteria userData;
421  if (errNo)
422  {
423  *errNo = ENOENT;
424  }
425  char *c = getenv ("DCE_ROOT");
426  if (c)
427  {
428  altRoots = c;
429  }
430  userData.uid = uid;
431  userData.gid = gid;
432  userData.errNo = errNo;
433 
434  return SearchFile (file, vroot, cwd, altRoots, &userData, CheckFileExe);
435 }
436 // Search using only a real path within a real environment variable
437 std::string
438 SearchExecFile (std::string envVar, std::string file, int *errNo)
439 {
440  char *c = getenv (envVar.c_str ());
441  std::string dcepath = "";
442  struct ExeCriteria userData;
443 
444  if (c)
445  {
446  dcepath = c;
447  }
448  userData.uid = 0;
449  userData.gid = 0;
450  userData.errNo = 0;
451 
452  return SearchFile (file, "", "", dcepath, "", "", &userData, CheckFileExe);
453 }
454 
455 }