ns-3 Direct Code Execution
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
dce.cc
Go to the documentation of this file.
1 #include "dce-manager.h"
2 #include "process.h"
3 #include "utils.h"
4 #include "exec-utils.h"
5 #include "dce-errno.h"
6 #include "dce-libc-private.h"
7 #include "dce-signal.h"
8 #include "dce-netdb.h"
9 #include "dce-unistd.h"
10 #include "dce-time.h"
11 #include "sys/dce-socket.h"
12 #include "dce-pthread.h"
13 #include "dce-stdio.h"
14 #include "dce-stdarg.h"
15 #include "dce-stdlib.h"
16 #include "dce-locale.h"
17 #include "sys/dce-ioctl.h"
18 #include "dce-sched.h"
19 #include "arpa/dce-inet.h"
20 #include <stdlib.h>
21 #include <string.h>
22 #include <getopt.h>
23 #include <limits.h>
24 #include <fcntl.h>
25 #include <net/if.h>
26 #include <sys/ioctl.h>
27 #include "dce-random.h"
28 #include "net/dce-if.h"
29 #include "ns3/node.h"
30 #include "ns3/log.h"
31 #include "ns3/simulator.h"
32 #include "ns3/names.h"
33 #include "ns3/random-variable.h"
34 #include "ns3/ipv4-l3-protocol.h"
35 #include "socket-fd-factory.h"
36 
38 
39 using namespace ns3;
40 
42 {
44  return &current->err;
45 }
46 pid_t dce_getpid (void)
47 {
49  return current->process->pid;
50 }
51 pid_t dce_getppid (void)
52 {
54  return current->process->ppid;
55 }
56 uid_t dce_getuid (void)
57 {
59  return current->process->ruid;
60 }
61 uid_t dce_geteuid (void)
62 {
64  return current->process->euid;
65 }
66 static bool is_ucapable (void)
67 {
69  return current->process->euid == 0;
70 }
71 static bool is_gcapable (void)
72 {
74  return current->process->egid == 0;
75 }
76 static bool is_set_ucapable (uid_t uid)
77 {
78  GET_CURRENT (uid);
79  return is_ucapable ()
80  || current->process->euid == uid
81  || current->process->ruid == uid
82  || current->process->suid == uid;
83 }
84 static bool is_set_gcapable (gid_t gid)
85 {
86  GET_CURRENT (gid);
87  return is_gcapable ()
88  || current->process->egid == gid
89  || current->process->rgid == gid
90  || current->process->sgid == gid;
91 }
92 
93 int dce_setresuid (uid_t ruid, uid_t euid, uid_t suid)
94 {
95  GET_CURRENT (ruid << euid << suid);
96  if (ruid != (uid_t)-1
97  && !is_set_ucapable (ruid))
98  {
99  current->err = EPERM;
100  return -1;
101  }
102  if (euid != (uid_t)-1
103  && !is_set_ucapable (euid))
104  {
105  current->err = EPERM;
106  return -1;
107  }
108  if (suid != (uid_t)-1
109  && !is_set_ucapable (suid))
110  {
111  current->err = EPERM;
112  return -1;
113  }
114  if (ruid != (uid_t)-1)
115  {
116  current->process->ruid = ruid;
117  }
118  if (euid != (uid_t)-1)
119  {
120  current->process->euid = euid;
121  }
122  if (suid != (uid_t)-1)
123  {
124  current->process->suid = suid;
125  }
126 
127  return 0;
128 }
129 int dce_setresgid (gid_t rgid, gid_t egid, gid_t sgid)
130 {
131  GET_CURRENT (rgid << egid << sgid);
132  if (rgid != (gid_t)-1
133  && !is_set_ucapable (rgid))
134  {
135  current->err = EPERM;
136  return -1;
137  }
138  if (egid != (gid_t)-1
139  && !is_set_ucapable (egid))
140  {
141  current->err = EPERM;
142  return -1;
143  }
144  if (sgid != (gid_t)-1
145  && !is_set_ucapable (sgid))
146  {
147  current->err = EPERM;
148  return -1;
149  }
150  if (rgid != (gid_t)-1)
151  {
152  current->process->rgid = rgid;
153  }
154  if (egid != (gid_t)-1)
155  {
156  current->process->egid = egid;
157  }
158  if (sgid != (gid_t)-1)
159  {
160  current->process->sgid = sgid;
161  }
162  return 0;
163 }
164 int dce_setreuid (uid_t ruid, uid_t euid)
165 {
166  GET_CURRENT (ruid << euid);
167  return dce_setresuid (ruid,euid,-1);
168 }
169 int dce_setregid (gid_t rgid, gid_t egid)
170 {
171  GET_CURRENT (rgid << egid);
172  return dce_setresgid (rgid,egid,-1);
173 }
174 
175 int dce_seteuid (uid_t euid)
176 {
177  GET_CURRENT (euid);
178  return dce_setresuid (-1, euid, -1);
179 }
180 int dce_setegid (gid_t egid)
181 {
182  GET_CURRENT (egid);
183  return dce_setresgid (-1, egid, -1);
184 }
185 int dce_setuid (uid_t uid)
186 {
187  GET_CURRENT (uid);
188  if (is_set_ucapable (uid))
189  {
190  current->process->ruid = uid;
191  if (current->process->euid == 0)
192  {
193  current->process->euid = uid;
194  current->process->suid = uid;
195  }
196  return 0;
197  }
198  else
199  {
200  current->err = EPERM;
201  return -1;
202  }
203 }
204 int dce_setgid (gid_t gid)
205 {
206  GET_CURRENT (gid);
207  if (is_set_gcapable (gid))
208  {
209  current->process->rgid = gid;
210  if (current->process->egid == 0)
211  {
212  current->process->egid = gid;
213  current->process->sgid = gid;
214  }
215  return 0;
216  }
217  else
218  {
219  current->err = EPERM;
220  return -1;
221  }
222 }
223 
224 unsigned int dce_sleep (unsigned int seconds)
225 {
226  Thread *current = Current ();
227  NS_LOG_FUNCTION (current << UtilsGetNodeId ());
228  NS_ASSERT (current != 0);
229  current->process->manager->Wait (Seconds (seconds));
230  return 0;
231 }
232 int dce_usleep (useconds_t usec)
233 {
234  Thread *current = Current ();
235  NS_LOG_FUNCTION (current << UtilsGetNodeId ());
236  NS_ASSERT (current != 0);
237  current->process->manager->Wait (MicroSeconds (usec));
238  return 0;
239 }
240 
241 int dce_kill (pid_t pid, int sig)
242 {
243  Thread *current = Current ();
244  NS_LOG_FUNCTION (current << UtilsGetNodeId () << pid << sig);
245  Process *process = current->process->manager->SearchProcess (pid);
246 
247  if (process == 0)
248  {
249  current->err = ESRCH;
250  return -1;
251  }
252 
253  UtilsSendSignal (process, SIGKILL);
254 
255  return 0;
256 }
257 
258 void dce_abort ()
259 {
260  Thread *current = Current ();
261  NS_LOG_FUNCTION (current);
262 
263  UtilsSendSignal (Current ()->process, SIGABRT);
264  // If we are still alive force the exitation
265  dce_exit (-2);
266 }
267 
268 int dce_pause (void)
269 {
270  //Thread *current = Current ();
271  //NS_LOG_FUNCTION (current << UtilsGetNodeId ());
272  //NS_ASSERT (current != 0);
273  // XXX
274  return 0;
275 }
276 
277 
278 int dce_gettimeofday (struct timeval *tv, struct timezone *tz)
279 {
280  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
281  NS_ASSERT (Current () != 0);
282  NS_ASSERT (tz == 0);
284  return 0;
285 }
286 int dce_nanosleep (const struct timespec *req, struct timespec *rem)
287 {
288  Thread *current = Current ();
289  NS_LOG_FUNCTION (current << UtilsGetNodeId ());
290  NS_ASSERT (current != 0);
291  if (req == 0)
292  {
293  current->err = EFAULT;
294  return -1;
295  }
296  if ((req->tv_sec < 0) || (req->tv_nsec < 0) || (req->tv_nsec > 999999999))
297  {
298  current->err = EINVAL;
299  return -1;
300  }
301  Time reqTime = UtilsTimespecToTime (*req);
302  Time remTime = current->process->manager->Wait (reqTime);
303  if (remTime == Seconds (0.0))
304  {
305  return 0;
306  }
307  else
308  {
309  current->err = EINTR;
310  if (rem != 0)
311  {
312  *rem = UtilsTimeToTimespec (remTime);
313  }
314  return -1;
315  }
316 }
317 
318 long int dce_random (void)
319 {
320  Thread *current = Current ();
321  return current->process->rndVarible.GetInteger ();
322 }
323 int dce_rand (void)
324 {
325  Thread *current = Current ();
326  return current->process->rndVarible.GetInteger ();
327 }
328 unsigned short int * dce_seed48 (unsigned short int seed16v[3])
329 {
330  Thread *current = Current ();
331  seed48_r (seed16v, &(current->process->seed48Current));
332 
333  return current->process->seed48Current.__old_x;
334 }
335 double dce_drand48 (void)
336 {
337  Thread *current = Current ();
338  double res;
339 
340  drand48_r (&(current->process->seed48Current), &res);
341 
342  return res;
343 }
344 long int dce_nrand48 (unsigned short int xsubi[3])
345 {
346  Thread *current = Current ();
347 
348  long int res = 0;
349 
350  nrand48_r (xsubi, &(current->process->seed48Current), &res);
351 
352  return res;
353 }
354 long int dce_lrand48 (void)
355 {
356  Thread *current = Current ();
357 
358  long int res = 0;
359 
360  lrand48_r (&(current->process->seed48Current), &res);
361 
362  return res;
363 }
364 
365 long int dce_mrand48 (void)
366 {
367  Thread *current = Current ();
368 
369  long int res;
370 
371  jrand48_r (current->process->seed48Current.__x, &(current->process->seed48Current), &res);
372 
373  return res;
374 }
375 
376 double dce_erand48 (unsigned short xsubi[3])
377 {
378  Thread *current = Current ();
379  double res;
380 
381  erand48_r (xsubi, &(current->process->seed48Current), &res);
382 
383  return res;
384 }
385 long int dce_jrand48 (unsigned short int xsubi[3])
386 {
387  Thread *current = Current ();
388 
389  long int res = 0;
390 
391  jrand48_r (xsubi, &(current->process->seed48Current), &res);
392 
393  return res;
394 }
395 
396 void dce_srand48 (long int seedval)
397 {
398  Thread *current = Current ();
399 
400  srand48_r (seedval, &(current->process->seed48Current));
401 }
402 
403 void dce_lcong48 (unsigned short param[7])
404 {
405  Thread *current = Current ();
406 
407  lcong48_r (param, &(current->process->seed48Current));
408 }
409 
410 //ignore seeds as RandomVariable implementation ensures that we take different random streams.
411 //TODO: support getting the same rng stream for several processes
412 void dce_srandom (unsigned int seed)
413 {
414  return;
415 }
416 void dce_srand (unsigned int seed)
417 {
418  return;
419 }
420 
421 const char * dce_inet_ntop (int af, const void *src,
422  char *dst, socklen_t cnt)
423 {
424  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << af << src << dst << cnt);
425  Thread *current = Current ();
426  const char *retval = inet_ntop (af, src, dst, cnt);
427  if (retval == 0)
428  {
429  current->err = errno;
430  }
431  return retval;
432 }
433 int dce_getopt (int argc, char * const argv[], const char *optstring)
434 {
435  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << argc << argv << optstring);
436  NS_ASSERT (Current () != 0);
437  Process *process = Current ()->process;
438 
439  /* The following is pretty evil but it all comes down to the fact
440  * that the libc does not export getopt_internal_r which is really the
441  * function we want to call here.
442  */
443  char *optargsaved = optarg;
444  int optindsaved = optind;
445  int opterrsaved = opterr;
446  int optoptsaved = optopt;
447  optarg = *process->poptarg;
448  optind = *process->poptind;
449  opterr = *process->popterr;
450  optopt = *process->poptopt;
451  int retval = getopt (argc, argv, optstring);
452  *process->poptarg = optarg;
453  *process->poptind = optind;
454  *process->popterr = opterr;
455  *process->poptopt = optopt;
456  optarg = optargsaved;
457  optind = optindsaved;
458  opterr = opterrsaved;
459  optopt = optoptsaved;
460  return retval;
461 }
462 int dce_getopt_long (int argc, char * const argv[], const char *optstring,
463  const struct option *longopts, int *longindex)
464 {
465  NS_LOG_FUNCTION (Current () << "node" << UtilsGetNodeId () << argc << argv << optstring <<
466  longopts << longindex);
467  NS_ASSERT (Current () != 0);
468  Process *process = Current ()->process;
469 
470  /* The following is pretty evil but it all comes down to the fact
471  * that the libc does not export getopt_internal_r which is really the
472  * function we want to call here.
473  */
474  char *optargsaved = optarg;
475  int optindsaved = optind;
476  int opterrsaved = opterr;
477  int optoptsaved = optopt;
478  optarg = *process->poptarg;
479  optind = *process->poptind;
480  opterr = *process->popterr;
481  optopt = *process->poptopt;
482  int retval = getopt_long (argc, argv, optstring, longopts, longindex);
483  *process->poptarg = optarg;
484  *process->poptind = optind;
485  *process->popterr = opterr;
486  *process->poptopt = optopt;
487  optarg = optargsaved;
488  optind = optindsaved;
489  opterr = opterrsaved;
490  optopt = optoptsaved;
491  return retval;
492 }
493 int dce_sched_yield (void)
494 {
495  Thread *current = Current ();
496  NS_LOG_FUNCTION (current << UtilsGetNodeId ());
497  NS_ASSERT (current != 0);
498  current->process->manager->Yield ();
499  return 0;
500 }
501 static void Itimer (Process *process)
502 {
503  if (!process->itimerInterval.IsZero ())
504  {
505  process->itimer = Simulator::Schedule (process->itimerInterval,
506  &Itimer, process);
507  }
508  // wakeup one thread
509  UtilsSendSignal (process, SIGALRM);
510 }
511 int dce_getitimer (int which, struct itimerval *value)
512 {
513 
514  Thread *current = Current ();
515  NS_LOG_FUNCTION (current << UtilsGetNodeId () << which << value);
516  NS_ASSERT (current != 0);
517  if (value == 0)
518  {
519  current->err = EFAULT;
520  return -1;
521  }
522  // We don't support other kinds of timers.
523  NS_ASSERT (which == ITIMER_REAL);
524  value->it_interval = UtilsTimeToTimeval (current->process->itimerInterval);
525  value->it_value = UtilsTimeToTimeval (Simulator::GetDelayLeft (current->process->itimer));
526  return 0;
527 }
528 int dce_setitimer (int which, const struct itimerval *value,
529  struct itimerval *ovalue)
530 {
531  Thread *current = Current ();
532  NS_LOG_FUNCTION (current << UtilsGetNodeId () << which << value << ovalue);
533  NS_ASSERT (current != 0);
534  if (value == 0)
535  {
536  current->err = EINVAL;
537  return -1;
538  }
539  // We don't support other kinds of timers.
540  NS_ASSERT (which == ITIMER_REAL);
541  if (ovalue != 0)
542  {
543  ovalue->it_interval = UtilsTimeToTimeval (current->process->itimerInterval);
544  ovalue->it_value = UtilsTimeToTimeval (Simulator::GetDelayLeft (current->process->itimer));
545  }
546 
547  current->process->itimer.Cancel ();
548  current->process->itimerInterval = UtilsTimevalToTime (value->it_interval);
549  if (value->it_value.tv_sec == 0
550  && value->it_value.tv_usec == 0)
551  {
552  return 0;
553  }
554  TaskManager *manager = TaskManager::Current ();
555  current->process->itimer = manager->ScheduleMain (
556  UtilsTimevalToTime (value->it_value),
557  MakeEvent (&Itimer, current->process));
558 
559  return 0;
560 }
561 char * dce_getcwd (char *buf, size_t size)
562 {
563  Thread *current = Current ();
564  NS_ASSERT (current != 0);
565  NS_LOG_FUNCTION (current << UtilsGetNodeId ());
566  uint32_t cwd_size = current->process->cwd.size ();
567  if ((buf != 0 && size < cwd_size + 1)
568  || (buf == 0 && size != 0 && size < cwd_size + 1))
569  {
570  current->err = ERANGE;
571  return 0;
572  }
573  // from here on, we know that we will have enough space
574  // in the buffer for the strcpy
575  if (buf == 0)
576  {
577  if (size == 0)
578  {
579  buf = (char *)dce_malloc (cwd_size + 1);
580  size = cwd_size + 1;
581  }
582  else
583  {
584  buf = (char *)dce_malloc (size);
585  }
586  buf[size - 1] = 0;
587  }
588  const char *source = current->process->cwd.c_str ();
589  strcpy (buf, source);
590  return buf;
591 }
592 char * dce_getwd (char *buf)
593 {
594  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << buf);
595  NS_ASSERT (Current () != 0);
596  Thread *current = Current ();
597  uint32_t cwd_size = current->process->cwd.size ();
598  if (PATH_MAX < cwd_size + 1)
599  {
600  current->err = ENAMETOOLONG;
601  return 0;
602  }
603  const char *source = current->process->cwd.c_str ();
604  strcpy (buf, source);
605  return buf;
606 }
608 {
609  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
610  NS_ASSERT (Current () != 0);
611  return dce_getcwd (0, 0);
612 }
613 
614 int dce_chdir (const char *path)
615 {
616  Thread *current = Current ();
617  NS_LOG_FUNCTION (current << UtilsGetNodeId ());
618  NS_ASSERT (current != 0);
619 
620  int retval;
621  std::string newCwd = UtilsGetRealFilePath (path);
622  // test to see if the target directory exists
623  retval = ::open (newCwd.c_str (), O_DIRECTORY | O_RDONLY);
624  if (retval == -1)
625  {
626  current->err = errno;
627  return -1;
628  }
629  ::close (retval);
630  current->process->cwd = UtilsGetVirtualFilePath (path);
631  return 0;
632 }
633 int dce_fchdir (int fd)
634 {
635  Thread *current = Current ();
636  NS_LOG_FUNCTION (current << UtilsGetNodeId ());
637  NS_ASSERT (current != 0);
638  int realFd = getRealFd (fd, current);
639 
640  if (realFd < 0)
641  {
642  current->err = EBADF;
643  return -1;
644  }
645  std::string p = PathOfFd (realFd);
646 
647  if (0 == p.length ())
648  {
649  current->err = EBADF;
650  return -1;
651  }
652  std::string base = UtilsGetCurrentDirName () + "/" + UtilsGetRealFilePath ("/");
653  current->process->cwd = UtilsGetVirtualFilePath (std::string (p, base.length () - 1));
654  return 0;
655 }
656 unsigned dce_if_nametoindex (const char *ifname)
657 {
658  Thread *current = Current ();
659  Ptr<SocketFdFactory> factory = 0;
660  factory = current->process->manager->GetObject<SocketFdFactory> ();
661 
662  if (factory->GetInstanceTypeId () == TypeId::LookupByName ("ns3::LinuxSocketFdFactory"))
663  {
664  struct ifreq ifr;
665  int fd = dce_socket (AF_INET, SOCK_DGRAM, 0);
666  if (fd < 0)
667  {
668  return 0;
669  }
670 
671  strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
672  if (dce_ioctl (fd, SIOCGIFINDEX, (char *)&ifr) < 0)
673  {
674  current->err = errno;
675  return -1;
676  }
677  return ifr.ifr_ifindex;
678  }
679  else
680  {
681  int index = 0;
682  Ptr<Node> node = Current ()->process->manager->GetObject<Node> ();
683  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
684 
685  for (uint32_t i = 0; i < node->GetNDevices (); ++i)
686  {
687  Ptr<NetDevice> dev = node->GetDevice (i);
688  if (ifname == Names::FindName (dev))
689  {
690  index = ipv4->GetInterfaceForDevice (dev);
691  return index;
692  }
693  }
694  return 0;
695  }
696 }
697 char * dce_if_indextoname (unsigned ifindex, char *ifname)
698 {
699  struct ifreq ifr;
700  int fd = dce_socket (AF_INET, SOCK_DGRAM, 0);
701  if (fd < 0)
702  {
703  return 0;
704  }
705 
706  ifr.ifr_ifindex = ifindex;
707  if (dce_ioctl (fd, SIOCGIFNAME, (char *)&ifr) < 0)
708  {
709  return 0;
710  }
711  return strncpy (ifname, ifr.ifr_name, IFNAMSIZ);
712 }
713 pid_t dce_fork (void)
714 {
715  Thread *thread = Current ();
716  NS_LOG_FUNCTION (thread);
717  DceManager *manager = thread->process->manager;
718  return manager->Clone (thread);
719 }
720 
721 int dce_execv (const char *path, char *const argv[])
722 {
723  Thread *thread = Current ();
724  NS_LOG_FUNCTION (thread << UtilsGetNodeId () << path);
725 
726  std::string fileName = SearchExecFile (path, getuid (), getgid (), &(thread->err));
727 
728  if (0 == fileName.length ())
729  {
730  // Errno setted by FindExecFile
731  return -1;
732  }
733 
734  return thread->process->manager->Execve (fileName.c_str (), path, argv, *(thread->process->penvp));
735 }
736 int dce_execl (const char *path, const char *arg, ...)
737 {
738  va_list ap;
739  va_start (ap, arg);
740 
741  Thread *thread = Current ();
742  NS_LOG_FUNCTION (thread << UtilsGetNodeId () << path);
743 
744  std::string fileName = SearchExecFile (path, getuid (), getgid (), &(thread->err));
745 
746  if (0 == fileName.length ())
747  {
748  // Errno setted by FindExecFile
749  return -1;
750  }
751 
752  int nb = 1;
753 
754  va_list cp;
755  va_copy (cp, ap);
756  char *p = 0;
757  do
758  {
759  p = va_arg (cp, char *);
760  nb++;
761  }
762  while (p);
763 
764  char const** argv = (char const **) dce_malloc (nb * sizeof (char *)); // Use dce_malloc to be sure it will be freed when exec is successfull
765 
766  argv[0] = arg;
767  nb = 1;
768 
769  do
770  {
771  argv[nb++] = p = va_arg (ap, char *);
772  }
773  while (p);
774 
775  int retval = thread->process->manager->Execve (fileName.c_str (), path, (char* const*) argv, *(thread->process->penvp));
776 
777  dce_free (argv);
778 
779  return retval;
780 }
781 int dce_execve (const char *path, char *const argv[], char *const envp[])
782 {
783  Thread *thread = Current ();
784  NS_LOG_FUNCTION (thread << UtilsGetNodeId () << path);
785 
786  std::string fileName = SearchExecFile (path, getuid (), getgid (), &(thread->err));
787 
788  if (0 == fileName.length ())
789  {
790  // Errno setted by FindExecFile
791  return -1;
792  }
793 
794  return thread->process->manager->Execve (fileName.c_str (), path, argv, envp);
795 }
796 
797 int dce_execlp (const char *file, const char *arg, ...)
798 {
799  va_list ap;
800  va_start (ap, arg);
801 
802  Thread *thread = Current ();
803  NS_LOG_FUNCTION (thread << UtilsGetNodeId () << file);
804 
805  std::string vpath = "";
806  char *pvpath = seek_env ("PATH", *thread->process->penvp);
807  if (pvpath)
808  {
809  vpath = std::string (pvpath);
810  }
811  std::string fileName = file;
812 
813  fileName = SearchExecFile (fileName, vpath, getuid (), getgid (), &(thread->err));
814 
815  if (0 == fileName.length ())
816  {
817  // Errno setted by FindExecFile
818  return -1;
819  }
820 
821  int nb = 1;
822  va_list cp;
823  va_copy (cp, ap);
824  char *p = 0;
825  do
826  {
827  p = va_arg (cp, char *);
828  nb++;
829  }
830  while (p);
831 
832  char const** argv = (char const **) dce_malloc (nb * sizeof (char *)); // Use dce_malloc to be sure it will be freed when exec is successfull
833 
834  argv[0] = arg;
835  nb = 1;
836 
837  do
838  {
839  argv[nb++] = p = va_arg (ap, char *);
840  }
841  while (p);
842 
843  int retval = thread->process->manager->Execve (fileName.c_str (), file, (char* const*) argv, *(thread->process->penvp));
844 
845  dce_free (argv);
846 
847  return retval;
848 }
849 int dce_execvp (const char *file, char *const argv[])
850 {
851  Thread *thread = Current ();
852  NS_LOG_FUNCTION (thread << UtilsGetNodeId () << file);
853 
854  std::string vpath = "";
855  char *pvpath = seek_env ("PATH", *thread->process->penvp);
856  if (pvpath)
857  {
858  vpath = std::string (pvpath);
859  }
860  std::string fileName = file;
861  fileName = SearchExecFile (fileName, vpath, getuid (), getgid (), &(thread->err));
862  if (0 == fileName.length ())
863  {
864  // Errno setted by FindExecFile
865  return -1;
866  }
867 
868  return thread->process->manager->Execve (fileName.c_str (), file, argv, *(thread->process->penvp));
869 }
870 int dce_execle (const char *path, const char *arg, ...)
871 {
872  va_list ap;
873  va_start (ap, arg);
874 
875  Thread *thread = Current ();
876  NS_LOG_FUNCTION (thread << UtilsGetNodeId () << path);
877  std::string fileName = SearchExecFile (path, getuid (), getgid (), &(thread->err));
878 
879  if (0 == fileName.length ())
880  {
881  // Errno setted by FindExecFile
882  return -1;
883  }
884  int nb = 1;
885  va_list cp;
886  va_copy (cp, ap);
887  char *p = 0;
888  do
889  {
890  p = va_arg (cp, char *);
891  nb++;
892  }
893  while (p);
894 
895  char const** envp = (char const **) va_arg (cp, char **);
896  char const** argv = (char const **) dce_malloc (nb * sizeof (char *)); // Use dce_malloc to be sure it will be freed when exec is successfull
897 
898  argv[0] = arg;
899  nb = 1;
900 
901  do
902  {
903  argv[nb++] = p = va_arg (ap, char *);
904  }
905  while (p);
906 
907  int retval = thread->process->manager->Execve (fileName.c_str (), path,
908  (char* const*) argv, (char* const*) envp);
909 
910  dce_free (argv);
911 
912  return retval;
913 }
914 
915 char * dce_setlocale (int category, const char *locale)
916 {
917  static char loc[] = "";
918  return loc;
919 }
920 int dce_sysinfo (struct sysinfo *info)
921 {
922  Thread *current = Current ();
923  NS_LOG_FUNCTION (current << UtilsGetNodeId ());
924  NS_ASSERT (current != 0);
925  if (!info)
926  {
927  current->err = ENAMETOOLONG;
928  return -1;
929  }
930 
931  info->uptime = (long)UtilsSimulationTimeToTime (Now ()).GetSeconds ();
932  // XXX
933  return 0;
934 }
935 int dce_daemon (int nochdir, int noclose)
936 {
937  return 0;
938 }
939 unsigned int dce_alarm (unsigned int s)
940 {
941  struct itimerval it;
942  memset (&it, 0, sizeof (it));
943 
944  unsigned int ret = 0;
945 
946  if (!dce_getitimer (ITIMER_REAL, &it))
947  {
948  ret = it.it_value.tv_sec;
949  }
950 
951  memset (&it, 0, sizeof (it));
952  it.it_value.tv_sec = s;
953  it.it_value.tv_usec = 0;
954 
955  dce_setitimer (ITIMER_REAL, &it, NULL);
956 
957  return ret;
958 }
959 ssize_t dce_readlink (const char *path, char *buf, size_t bufsize)
960 {
961  Thread *current = Current ();
962  NS_LOG_FUNCTION (current << UtilsGetNodeId ());
963  NS_ASSERT (current != 0);
964 
965  std::string fullpath = UtilsGetRealFilePath (path);
966 
967  ssize_t ret = readlink (fullpath.c_str (), buf, bufsize);
968 
969  if (ret)
970  {
971  current->err = errno;
972  return ret;
973  }
974 
975  int l = UtilsGetRealFilePath ("/").length ();
976 
977  memcpy (buf, buf + l, l);
978  buf [l] = 0;
979 
980  return 0;
981 }
982 #ifdef HAVE_GETCPUFEATURES
983 extern "C"
984 {
985 extern const struct cpu_features * __get_cpu_features (void);
986 }
987 const struct cpu_features * dce___get_cpu_features (void)
988 {
989  return __get_cpu_features ();
990 }
991 #endif // HAVE_GETCPUFEATURES