Logo ROOT   6.07/09
Reference Guide
TUnixSystem.cxx
Go to the documentation of this file.
1 // @(#)root/unix:$Id: 887c618d89c4ed436e4034fc133f468fecad651b $
2 // Author: Fons Rademakers 15/09/95
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////
13 // //
14 // TUnixSystem //
15 // //
16 // Class providing an interface to the UNIX Operating System. //
17 // //
18 //////////////////////////////////////////////////////////////////////////
19 
20 #include "RConfigure.h"
21 #include "RConfig.h"
22 #include "TUnixSystem.h"
23 #include "TROOT.h"
24 #include "TError.h"
25 #include "TOrdCollection.h"
26 #include "TRegexp.h"
27 #include "TPRegexp.h"
28 #include "TException.h"
29 #include "Demangle.h"
30 #include "TEnv.h"
31 #include "TSocket.h"
32 #include "Getline.h"
33 #include "TInterpreter.h"
34 #include "TApplication.h"
35 #include "TObjString.h"
36 #include "Riostream.h"
37 #include "TVirtualMutex.h"
38 #include "TObjArray.h"
39 #include <map>
40 #include <algorithm>
41 #include <atomic>
42 
43 //#define G__OLDEXPAND
44 
45 #include <unistd.h>
46 #include <stdlib.h>
47 #include <sys/types.h>
48 #if defined(R__SUN) || defined(R__AIX) || \
49  defined(R__LINUX) || defined(R__SOLARIS) || \
50  defined(R__FBSD) || defined(R__OBSD) || \
51  defined(R__MACOSX) || defined(R__HURD)
52 #define HAS_DIRENT
53 #endif
54 #ifdef HAS_DIRENT
55 # include <dirent.h>
56 #else
57 # include <sys/dir.h>
58 #endif
59 #if defined(ULTRIX) || defined(R__SUN)
60 # include <sgtty.h>
61 #endif
62 #if defined(R__AIX) || defined(R__LINUX) || \
63  defined(R__FBSD) || defined(R__OBSD) || \
64  defined(R__LYNXOS) || defined(R__MACOSX) || defined(R__HURD)
65 # include <sys/ioctl.h>
66 #endif
67 #if defined(R__AIX) || defined(R__SOLARIS)
68 # include <sys/select.h>
69 #endif
70 #if defined(R__LINUX) || defined(R__HURD)
71 # ifndef SIGSYS
72 # define SIGSYS SIGUNUSED // SIGSYS does not exist in linux ??
73 # endif
74 #endif
75 #if defined(R__MACOSX)
76 # include <mach-o/dyld.h>
77 # include <sys/mount.h>
78  extern "C" int statfs(const char *file, struct statfs *buffer);
79 #elif defined(R__LINUX) || defined(R__HURD)
80 # include <sys/vfs.h>
81 #elif defined(R__FBSD) || defined(R__OBSD)
82 # include <sys/param.h>
83 # include <sys/mount.h>
84 #else
85 # include <sys/statfs.h>
86 #endif
87 
88 #include <utime.h>
89 #include <syslog.h>
90 #include <sys/stat.h>
91 #include <setjmp.h>
92 #include <signal.h>
93 #include <sys/param.h>
94 #include <pwd.h>
95 #include <grp.h>
96 #include <errno.h>
97 #include <sys/resource.h>
98 #include <sys/wait.h>
99 #include <time.h>
100 #include <sys/time.h>
101 #include <sys/file.h>
102 #include <sys/socket.h>
103 #include <netinet/in.h>
104 #include <netinet/tcp.h>
105 #if defined(R__AIX)
106 # define _XOPEN_EXTENDED_SOURCE
107 # include <arpa/inet.h>
108 # undef _XOPEN_EXTENDED_SOURCE
109 # if !defined(_AIX41) && !defined(_AIX43)
110  // AIX 3.2 doesn't have it
111 # define HASNOT_INETATON
112 # endif
113 #else
114 # include <arpa/inet.h>
115 #endif
116 #include <sys/un.h>
117 #include <netdb.h>
118 #include <fcntl.h>
119 #if defined(R__SOLARIS)
120 # include <sys/systeminfo.h>
121 # include <sys/filio.h>
122 # include <sys/sockio.h>
123 # define HASNOT_INETATON
124 # ifndef INADDR_NONE
125 # define INADDR_NONE (UInt_t)-1
126 # endif
127 #endif
128 
129 #if defined(R__SOLARIS)
130 # define HAVE_UTMPX_H
131 # define UTMP_NO_ADDR
132 #endif
133 
134 #if defined(MAC_OS_X_VERSION_10_5)
135 # define HAVE_UTMPX_H
136 # define UTMP_NO_ADDR
137 #endif
138 
139 #if defined(R__FBSD)
140 # include <sys/param.h>
141 # if __FreeBSD_version >= 900007
142 # define HAVE_UTMPX_H
143 # endif
144 #endif
145 
146 #if defined(R__AIX) || defined(R__FBSD) || \
147  defined(R__OBSD) || defined(R__LYNXOS) || \
148  (defined(R__MACOSX) && !defined(MAC_OS_X_VERSION_10_5))
149 # define UTMP_NO_ADDR
150 #endif
151 
152 #if (defined(R__AIX) && !defined(_AIX43)) || \
153  (defined(R__SUNGCC3) && !defined(__arch64__))
154 # define USE_SIZE_T
155 #elif defined(R__GLIBC) || defined(R__FBSD) || \
156  (defined(R__SUNGCC3) && defined(__arch64__)) || \
157  defined(R__OBSD) || defined(MAC_OS_X_VERSION_10_4) || \
158  (defined(R__AIX) && defined(_AIX43)) || \
159  (defined(R__SOLARIS) && defined(_SOCKLEN_T))
160 # define USE_SOCKLEN_T
161 #endif
162 
163 #if defined(R__LYNXOS)
164 extern "C" {
165  extern int putenv(const char *);
166  extern int inet_aton(const char *, struct in_addr *);
167 };
168 #endif
169 
170 #ifdef HAVE_UTMPX_H
171 #include <utmpx.h>
172 #define STRUCT_UTMP struct utmpx
173 #else
174 #include <utmp.h>
175 #define STRUCT_UTMP struct utmp
176 #endif
177 #if !defined(UTMP_FILE) && defined(_PATH_UTMP) // 4.4BSD
178 #define UTMP_FILE _PATH_UTMP
179 #endif
180 #if defined(UTMPX_FILE) // Solaris, SysVr4
181 #undef UTMP_FILE
182 #define UTMP_FILE UTMPX_FILE
183 #endif
184 #ifndef UTMP_FILE
185 #define UTMP_FILE "/etc/utmp"
186 #endif
187 
188 // stack trace code
189 #if (defined(R__LINUX) || defined(R__HURD)) && !defined(R__WINGCC)
190 # if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 1
191 # define HAVE_BACKTRACE_SYMBOLS_FD
192 # endif
193 # define HAVE_DLADDR
194 #endif
195 #if defined(R__MACOSX)
196 # define HAVE_BACKTRACE_SYMBOLS_FD
197 # define HAVE_DLADDR
198 #endif
199 
200 #ifdef HAVE_BACKTRACE_SYMBOLS_FD
201 # include <execinfo.h>
202 #endif
203 #ifdef HAVE_DLADDR
204 # ifndef __USE_GNU
205 # define __USE_GNU
206 # endif
207 # include <dlfcn.h>
208 #endif
209 
210 #ifdef HAVE_BACKTRACE_SYMBOLS_FD
211  // The maximum stack trace depth for systems where we request the
212  // stack depth separately (currently glibc-based systems).
213  static const int kMAX_BACKTRACE_DEPTH = 128;
214 #endif
215 
216 // FPE handling includes
217 #if (defined(R__LINUX) && !defined(R__WINGCC))
218 #include <fpu_control.h>
219 #include <fenv.h>
220 #include <sys/prctl.h> // for prctl() function used in StackTrace()
221 #endif
222 
223 #if defined(R__MACOSX) && defined(__SSE2__)
224 #include <xmmintrin.h>
225 #endif
226 
227 #if defined(R__MACOSX) && !defined(__SSE2__) && !defined(__xlC__) && \
228  !defined(__i386__) && !defined(__x86_64__) && !defined(__arm__) && \
229  !defined(__arm64__)
230 #include <fenv.h>
231 #include <signal.h>
232 #include <ucontext.h>
233 #include <stdlib.h>
234 #include <stdio.h>
235 #include <mach/thread_status.h>
236 
237 #define fegetenvd(x) asm volatile("mffs %0" : "=f" (x));
238 #define fesetenvd(x) asm volatile("mtfsf 255,%0" : : "f" (x));
239 
240 enum {
241  FE_ENABLE_INEXACT = 0x00000008,
242  FE_ENABLE_DIVBYZERO = 0x00000010,
243  FE_ENABLE_UNDERFLOW = 0x00000020,
244  FE_ENABLE_OVERFLOW = 0x00000040,
245  FE_ENABLE_INVALID = 0x00000080,
246  FE_ENABLE_ALL_EXCEPT = 0x000000F8
247 };
248 #endif
249 
250 #if defined(R__MACOSX) && !defined(__SSE2__) && \
251  (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__arm64__))
252 #include <fenv.h>
253 #endif
254 // End FPE handling includes
255 
256 namespace {
257  // Depending on the platform the struct utmp (or utmpx) has either ut_name or ut_user
258  // which are semantically equivalent. Instead of using preprocessor magic,
259  // which is bothersome for cxx modules use SFINAE.
260 
261  template<typename T>
262  struct ut_name {
263  template<typename U = T, typename std::enable_if<std::is_member_pointer<decltype(&U::ut_name)>::value, int>::type = 0>
264  static char getValue(U* ue, int) {
265  return ue->ut_name[0];
266  }
267 
268  template<typename U = T, typename std::enable_if<std::is_member_pointer<decltype(&U::ut_user)>::value, int>::type = 0>
269  static char getValue(U* ue, long) {
270  return ue->ut_user[0];
271  }
272  };
273 
274  static char get_ut_name(STRUCT_UTMP *ue) {
275  // 0 is an integer literal forcing an overload pickup in case both ut_name and ut_user are present.
276  return ut_name<STRUCT_UTMP>::getValue(ue, 0);
277  }
278 }
279 
280 struct TUtmpContent {
281  STRUCT_UTMP *fUtmpContents;
282  UInt_t fEntries; // Number of entries in utmp file.
283 
284  TUtmpContent() : fUtmpContents(0), fEntries(0) {}
285  ~TUtmpContent() { free(fUtmpContents); }
286 
287  STRUCT_UTMP *SearchUtmpEntry(const char *tty)
288  {
289  // Look for utmp entry which is connected to terminal tty.
290 
291  STRUCT_UTMP *ue = fUtmpContents;
292 
293  UInt_t n = fEntries;
294  while (n--) {
295  if (get_ut_name(ue) && !strncmp(tty, ue->ut_line, sizeof(ue->ut_line)))
296  return ue;
297  ue++;
298  }
299  return 0;
300  }
301 
302  int ReadUtmpFile()
303  {
304  // Read utmp file. Returns number of entries in utmp file.
305 
306  FILE *utmp;
307  struct stat file_stats;
308  size_t n_read, size;
309 
310  fEntries = 0;
311 
313 
314  utmp = fopen(UTMP_FILE, "r");
315  if (!utmp)
316  return 0;
317 
318  if (fstat(fileno(utmp), &file_stats) == -1) {
319  fclose(utmp);
320  return 0;
321  }
322  size = file_stats.st_size;
323  if (size <= 0) {
324  fclose(utmp);
325  return 0;
326  }
327 
328  fUtmpContents = (STRUCT_UTMP *) malloc(size);
329  if (!fUtmpContents) {
330  fclose(utmp);
331  return 0;
332  }
333 
334  n_read = fread(fUtmpContents, 1, size, utmp);
335  if (!ferror(utmp)) {
336  if (fclose(utmp) != EOF && n_read == size) {
337  fEntries = size / sizeof(STRUCT_UTMP);
338  return fEntries;
339  }
340  } else
341  fclose(utmp);
342 
343  free(fUtmpContents);
344  fUtmpContents = 0;
345  return 0;
346  }
347 
348 };
349 
350 const char *kServerPath = "/tmp";
351 const char *kProtocolName = "tcp";
352 
353 //------------------- Unix TFdSet ----------------------------------------------
354 #ifndef HOWMANY
355 # define HOWMANY(x, y) (((x)+((y)-1))/(y))
356 #endif
357 
358 const Int_t kNFDBITS = (sizeof(Long_t) * 8); // 8 bits per byte
359 #ifdef FD_SETSIZE
360 const Int_t kFDSETSIZE = FD_SETSIZE; // Linux = 1024 file descriptors
361 #else
362 const Int_t kFDSETSIZE = 256; // upto 256 file descriptors
363 #endif
364 
365 
366 class TFdSet {
367 private:
368  ULong_t fds_bits[HOWMANY(kFDSETSIZE, kNFDBITS)];
369 public:
370  TFdSet() { memset(fds_bits, 0, sizeof(fds_bits)); }
371  TFdSet(const TFdSet &org) { memcpy(fds_bits, org.fds_bits, sizeof(org.fds_bits)); }
372  TFdSet &operator=(const TFdSet &rhs) { if (this != &rhs) { memcpy(fds_bits, rhs.fds_bits, sizeof(rhs.fds_bits));} return *this; }
373  void Zero() { memset(fds_bits, 0, sizeof(fds_bits)); }
374  void Set(Int_t n)
375  {
376  if (n >= 0 && n < kFDSETSIZE) {
377  fds_bits[n/kNFDBITS] |= (1UL << (n % kNFDBITS));
378  } else {
379  ::Fatal("TFdSet::Set","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1);
380  }
381  }
382  void Clr(Int_t n)
383  {
384  if (n >= 0 && n < kFDSETSIZE) {
385  fds_bits[n/kNFDBITS] &= ~(1UL << (n % kNFDBITS));
386  } else {
387  ::Fatal("TFdSet::Clr","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1);
388  }
389  }
390  Int_t IsSet(Int_t n)
391  {
392  if (n >= 0 && n < kFDSETSIZE) {
393  return (fds_bits[n/kNFDBITS] & (1UL << (n % kNFDBITS))) != 0;
394  } else {
395  ::Fatal("TFdSet::IsSet","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1);
396  return 0;
397  }
398  }
399  ULong_t *GetBits() { return (ULong_t *)fds_bits; }
400 };
401 
402 ////////////////////////////////////////////////////////////////////////////////
403 /// Unix signal handler.
404 
405 static void SigHandler(ESignals sig)
406 {
407  if (gSystem)
408  ((TUnixSystem*)gSystem)->DispatchSignals(sig);
409 }
410 
411 ////////////////////////////////////////////////////////////////////////////////
412 
413 static const char *GetExePath()
414 {
415  TTHREAD_TLS_DECL(TString,exepath);
416  if (exepath == "") {
417 #if defined(R__MACOSX)
418  exepath = _dyld_get_image_name(0);
419 #elif defined(R__LINUX) || defined(R__SOLARIS) || defined(R__FBSD)
420  char buf[kMAXPATHLEN]; // exe path name
421 
422  // get the name from the link in /proc
423 #if defined(R__LINUX)
424  int ret = readlink("/proc/self/exe", buf, kMAXPATHLEN);
425 #elif defined(R__SOLARIS)
426  int ret = readlink("/proc/self/path/a.out", buf, kMAXPATHLEN);
427 #elif defined(R__FBSD)
428  int ret = readlink("/proc/curproc/file", buf, kMAXPATHLEN);
429 #endif
430  if (ret > 0 && ret < kMAXPATHLEN) {
431  buf[ret] = 0;
432  exepath = buf;
433  }
434 #else
435  if (!gApplication)
436  return exepath;
437  TString p = gApplication->Argv(0);
438  if (p.BeginsWith("/"))
439  exepath = p;
440  else if (p.Contains("/")) {
441  exepath = gSystem->WorkingDirectory();
442  exepath += "/";
443  exepath += p;
444  } else {
445  char *exe = gSystem->Which(gSystem->Getenv("PATH"), p, kExecutePermission);
446  if (exe) {
447  exepath = exe;
448  delete [] exe;
449  }
450  }
451 #endif
452  }
453  return exepath;
454 }
455 
456 #if defined(HAVE_DLADDR) && !defined(R__MACOSX)
457 ////////////////////////////////////////////////////////////////////////////////
458 
459 static void SetRootSys()
460 {
461 #ifndef ROOTPREFIX
462  void *addr = (void *)SetRootSys;
463  Dl_info info;
464  if (dladdr(addr, &info) && info.dli_fname && info.dli_fname[0]) {
465  char respath[kMAXPATHLEN];
466  if (!realpath(info.dli_fname, respath)) {
467  if (!gSystem->Getenv("ROOTSYS"))
468  ::SysError("TUnixSystem::SetRootSys", "error getting realpath of libCore, please set ROOTSYS in the shell");
469  } else {
470  TString rs = gSystem->DirName(respath);
471  gSystem->Setenv("ROOTSYS", gSystem->DirName(rs));
472  }
473  }
474 #else
475  return;
476 #endif
477 }
478 #endif
479 
480 #if defined(R__MACOSX)
481 static TString gLinkedDylibs;
482 
483 ////////////////////////////////////////////////////////////////////////////////
484 
485 static void DylibAdded(const struct mach_header *mh, intptr_t /* vmaddr_slide */)
486 {
487  static int i = 0;
488  static Bool_t gotFirstSo = kFALSE;
489  static TString linkedDylibs;
490 
491  // to copy the local linkedDylibs to the global gLinkedDylibs call this
492  // function with mh==0
493  if (!mh) {
494  gLinkedDylibs = linkedDylibs;
495  return;
496  }
497 
498  TString lib = _dyld_get_image_name(i++);
499 
500  TRegexp sovers = "libCore\\.[0-9]+\\.*[0-9]*\\.so";
501  TRegexp dyvers = "libCore\\.[0-9]+\\.*[0-9]*\\.dylib";
502 
503 #ifndef ROOTPREFIX
504 #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
505  // first loaded is the app so set ROOTSYS to app bundle
506  if (i == 1) {
507  char respath[kMAXPATHLEN];
508  if (!realpath(lib, respath)) {
509  if (!gSystem->Getenv("ROOTSYS"))
510  ::SysError("TUnixSystem::DylibAdded", "error getting realpath of %s", gSystem->BaseName(lib));
511  } else {
512  TString rs = gSystem->DirName(respath);
513  gSystem->Setenv("ROOTSYS", rs);
514  }
515  }
516 #else
517  if (lib.EndsWith("libCore.dylib") || lib.EndsWith("libCore.so") ||
518  lib.Index(sovers) != kNPOS || lib.Index(dyvers) != kNPOS) {
519  char respath[kMAXPATHLEN];
520  if (!realpath(lib, respath)) {
521  if (!gSystem->Getenv("ROOTSYS"))
522  ::SysError("TUnixSystem::DylibAdded", "error getting realpath of libCore, please set ROOTSYS in the shell");
523  } else {
524  TString rs = gSystem->DirName(respath);
525  gSystem->Setenv("ROOTSYS", gSystem->DirName(rs));
526  }
527  }
528 #endif
529 #endif
530 
531  // when libSystem.B.dylib is loaded we have finished loading all dylibs
532  // explicitly linked against the executable. Additional dylibs
533  // come when they are explicitly linked against loaded so's, currently
534  // we are not interested in these
535  if (lib.EndsWith("/libSystem.B.dylib"))
536  gotFirstSo = kTRUE;
537 
538  // add all libs loaded before libSystem.B.dylib
539  if (!gotFirstSo && (lib.EndsWith(".dylib") || lib.EndsWith(".so"))) {
540  sovers = "\\.[0-9]+\\.*[0-9]*\\.so";
541  Ssiz_t idx = lib.Index(sovers);
542  if (idx != kNPOS) {
543  lib.Remove(idx);
544  lib += ".so";
545  }
546  dyvers = "\\.[0-9]+\\.*[0-9]*\\.dylib";
547  idx = lib.Index(dyvers);
548  if (idx != kNPOS) {
549  lib.Remove(idx);
550  lib += ".dylib";
551  }
552  if (!gSystem->AccessPathName(lib, kReadPermission)) {
553  if (linkedDylibs.Length())
554  linkedDylibs += " ";
555  linkedDylibs += lib;
556  }
557  }
558 }
559 #endif
560 
562 
563 ////////////////////////////////////////////////////////////////////////////////
564 
565 TUnixSystem::TUnixSystem() : TSystem("Unix", "Unix System")
566 { }
567 
568 ////////////////////////////////////////////////////////////////////////////////
569 /// Reset to original state.
570 
572 {
573  UnixResetSignals();
574 
575  delete fReadmask;
576  delete fWritemask;
577  delete fReadready;
578  delete fWriteready;
579  delete fSignals;
580 }
581 
582 ////////////////////////////////////////////////////////////////////////////////
583 /// Initialize Unix system interface.
584 
586 {
587  if (TSystem::Init())
588  return kTRUE;
589 
590  fReadmask = new TFdSet;
591  fWritemask = new TFdSet;
592  fReadready = new TFdSet;
593  fWriteready = new TFdSet;
594  fSignals = new TFdSet;
595 
596  //--- install default handlers
597  UnixSignal(kSigChild, SigHandler);
598  UnixSignal(kSigBus, SigHandler);
600  UnixSignal(kSigIllegalInstruction, SigHandler);
601  UnixSignal(kSigSystem, SigHandler);
602  UnixSignal(kSigPipe, SigHandler);
603  UnixSignal(kSigAlarm, SigHandler);
604  UnixSignal(kSigUrgent, SigHandler);
605  UnixSignal(kSigFloatingException, SigHandler);
606  UnixSignal(kSigWindowChanged, SigHandler);
607 
608 #if defined(R__MACOSX)
609  // trap loading of all dylibs to register dylib name,
610  // sets also ROOTSYS if built without ROOTPREFIX
611  _dyld_register_func_for_add_image(DylibAdded);
612 #elif defined(HAVE_DLADDR)
613  SetRootSys();
614 #endif
615 
616 #ifndef ROOTPREFIX
617  gRootDir = Getenv("ROOTSYS");
618  if (gRootDir == 0)
619  gRootDir= "/usr/local/root";
620 #else
621  gRootDir = ROOTPREFIX;
622 #endif
623 
624  return kFALSE;
625 }
626 
627 //---- Misc --------------------------------------------------------------------
628 
629 ////////////////////////////////////////////////////////////////////////////////
630 /// Set the application name (from command line, argv[0]) and copy it in
631 /// gProgName. Copy the application pathname in gProgPath.
632 /// If name is 0 let the system set the actual executable name and path
633 /// (works on MacOS X and Linux).
634 
636 {
637  if (gProgName)
638  delete [] gProgName;
639  if (gProgPath)
640  delete [] gProgPath;
641 
642  if (!name || !*name) {
643  name = GetExePath();
644  gProgName = StrDup(BaseName(name));
645  gProgPath = StrDup(DirName(name));
646  } else {
647  gProgName = StrDup(BaseName(name));
648  char *w = Which(Getenv("PATH"), gProgName);
649  gProgPath = StrDup(DirName(w));
650  delete [] w;
651  }
652 }
653 
654 ////////////////////////////////////////////////////////////////////////////////
655 /// Set DISPLAY environment variable based on utmp entry. Only for UNIX.
656 
658 {
659  if (!Getenv("DISPLAY")) {
660  char *tty = ::ttyname(0); // device user is logged in on
661  if (tty) {
662  tty += 5; // remove "/dev/"
663 
664  TUtmpContent utmp;
665  utmp.ReadUtmpFile();
666 
667  STRUCT_UTMP *utmp_entry = utmp.SearchUtmpEntry(tty);
668  if (utmp_entry) {
669  if (utmp_entry->ut_host[0]) {
670  if (strchr(utmp_entry->ut_host, ':')) {
671  Setenv("DISPLAY", utmp_entry->ut_host);
672  Warning("SetDisplay", "DISPLAY not set, setting it to %s",
673  utmp_entry->ut_host);
674  } else {
675  char disp[64];
676  snprintf(disp, sizeof(disp), "%s:0.0", utmp_entry->ut_host);
677  Setenv("DISPLAY", disp);
678  Warning("SetDisplay", "DISPLAY not set, setting it to %s",
679  disp);
680  }
681  }
682 #ifndef UTMP_NO_ADDR
683  else if (utmp_entry->ut_addr) {
684 
685  struct sockaddr_in addr;
686  addr.sin_family = AF_INET;
687  addr.sin_port = 0;
688  memcpy(&addr.sin_addr, &utmp_entry->ut_addr, sizeof(addr.sin_addr));
689  memset(&addr.sin_zero[0], 0, sizeof(addr.sin_zero));
690  struct sockaddr *sa = (struct sockaddr *) &addr; // input
691 
692  char hbuf[NI_MAXHOST];
693  if (getnameinfo(sa, sizeof(struct sockaddr), hbuf, sizeof(hbuf), nullptr, 0, NI_NAMEREQD) == 0) {
694  char disp[64];
695  snprintf(disp, sizeof(disp), "%s:0.0", hbuf);
696  Setenv("DISPLAY", disp);
697  Warning("SetDisplay", "DISPLAY not set, setting it to %s",
698  disp);
699  }
700  }
701 #endif
702  }
703  }
704  }
705 }
706 
707 ////////////////////////////////////////////////////////////////////////////////
708 /// Return system error string.
709 
711 {
712  Int_t err = GetErrno();
713  if (err == 0 && GetLastErrorString() != "")
714  return GetLastErrorString();
715 
716 #if defined(R__SOLARIS) || defined (R__LINUX) || defined(R__AIX) || \
717  defined(R__FBSD) || defined(R__OBSD) || defined(R__HURD)
718  return strerror(err);
719 #else
720  if (err < 0 || err >= sys_nerr)
721  return Form("errno out of range %d", err);
722  return sys_errlist[err];
723 #endif
724 }
725 
726 ////////////////////////////////////////////////////////////////////////////////
727 /// Return the system's host name.
728 
730 {
731  if (fHostname == "") {
732  char hn[64];
733 #if defined(R__SOLARIS)
734  sysinfo(SI_HOSTNAME, hn, sizeof(hn));
735 #else
736  gethostname(hn, sizeof(hn));
737 #endif
738  fHostname = hn;
739  }
740  return (const char *)fHostname;
741 }
742 
743 //---- EventLoop ---------------------------------------------------------------
744 
745 ////////////////////////////////////////////////////////////////////////////////
746 /// Add a file handler to the list of system file handlers. Only adds
747 /// the handler if it is not already in the list of file handlers.
748 
750 {
752 
754  if (h) {
755  int fd = h->GetFd();
756  if (h->HasReadInterest()) {
757  fReadmask->Set(fd);
758  fMaxrfd = TMath::Max(fMaxrfd, fd);
759  }
760  if (h->HasWriteInterest()) {
761  fWritemask->Set(fd);
762  fMaxwfd = TMath::Max(fMaxwfd, fd);
763  }
764  }
765 }
766 
767 ////////////////////////////////////////////////////////////////////////////////
768 /// Remove a file handler from the list of file handlers. Returns
769 /// the handler or 0 if the handler was not in the list of file handlers.
770 
772 {
773  if (!h) return 0;
774 
776 
778  if (oh) { // found
779  TFileHandler *th;
780  TIter next(fFileHandler);
781  fMaxrfd = -1;
782  fMaxwfd = -1;
783  fReadmask->Zero();
784  fWritemask->Zero();
785  while ((th = (TFileHandler *) next())) {
786  int fd = th->GetFd();
787  if (th->HasReadInterest()) {
788  fReadmask->Set(fd);
789  fMaxrfd = TMath::Max(fMaxrfd, fd);
790  }
791  if (th->HasWriteInterest()) {
792  fWritemask->Set(fd);
793  fMaxwfd = TMath::Max(fMaxwfd, fd);
794  }
795  }
796  }
797  return oh;
798 }
799 
800 ////////////////////////////////////////////////////////////////////////////////
801 /// Add a signal handler to list of system signal handlers. Only adds
802 /// the handler if it is not already in the list of signal handlers.
803 
805 {
807 
809  UnixSignal(h->GetSignal(), SigHandler);
810 }
811 
812 ////////////////////////////////////////////////////////////////////////////////
813 /// Remove a signal handler from list of signal handlers. Returns
814 /// the handler or 0 if the handler was not in the list of signal handlers.
815 
817 {
818  if (!h) return 0;
819 
821 
823 
824  Bool_t last = kTRUE;
825  TSignalHandler *hs;
826  TIter next(fSignalHandler);
827 
828  while ((hs = (TSignalHandler*) next())) {
829  if (hs->GetSignal() == h->GetSignal())
830  last = kFALSE;
831  }
832  if (last)
833  ResetSignal(h->GetSignal(), kTRUE);
834 
835  return oh;
836 }
837 
838 ////////////////////////////////////////////////////////////////////////////////
839 /// If reset is true reset the signal handler for the specified signal
840 /// to the default handler, else restore previous behaviour.
841 
843 {
844  if (reset)
845  UnixResetSignal(sig);
846  else
847  UnixSignal(sig, SigHandler);
848 }
849 
850 ////////////////////////////////////////////////////////////////////////////////
851 /// Reset signals handlers to previous behaviour.
852 
854 {
855  UnixResetSignals();
856 }
857 
858 ////////////////////////////////////////////////////////////////////////////////
859 /// If ignore is true ignore the specified signal, else restore previous
860 /// behaviour.
861 
863 {
864  UnixIgnoreSignal(sig, ignore);
865 }
866 
867 ////////////////////////////////////////////////////////////////////////////////
868 /// When the argument is true the SIGALRM signal handler is set so that
869 /// interrupted syscalls will not be restarted by the kernel. This is
870 /// typically used in case one wants to put a timeout on an I/O operation.
871 /// By default interrupted syscalls will always be restarted (for all
872 /// signals). This can be controlled for each a-synchronous TTimer via
873 /// the method TTimer::SetInterruptSyscalls().
874 
876 {
877  UnixSigAlarmInterruptsSyscalls(set);
878 }
879 
880 ////////////////////////////////////////////////////////////////////////////////
881 /// Return the bitmap of conditions that trigger a floating point exception.
882 
884 {
885  Int_t mask = 0;
886 
887 #if defined(R__LINUX) && !defined(__powerpc__)
888 #if defined(__GLIBC__) && (__GLIBC__>2 || __GLIBC__==2 && __GLIBC_MINOR__>=1)
889 
890 #if __GLIBC_MINOR__>=3
891 
892  Int_t oldmask = fegetexcept();
893 
894 #else
895  fenv_t oldenv;
896  fegetenv(&oldenv);
897  fesetenv(&oldenv);
898 #if __ia64__
899  Int_t oldmask = ~oldenv;
900 #else
901  Int_t oldmask = ~oldenv.__control_word;
902 #endif
903 #endif
904 
905  if (oldmask & FE_INVALID ) mask |= kInvalid;
906  if (oldmask & FE_DIVBYZERO) mask |= kDivByZero;
907  if (oldmask & FE_OVERFLOW ) mask |= kOverflow;
908  if (oldmask & FE_UNDERFLOW) mask |= kUnderflow;
909 # ifdef FE_INEXACT
910  if (oldmask & FE_INEXACT ) mask |= kInexact;
911 # endif
912 #endif
913 #endif
914 
915 #if defined(R__MACOSX) && defined(__SSE2__)
916  // OS X uses the SSE unit for all FP math by default, not the x87 FP unit
917  Int_t oldmask = ~_MM_GET_EXCEPTION_MASK();
918 
919  if (oldmask & _MM_MASK_INVALID ) mask |= kInvalid;
920  if (oldmask & _MM_MASK_DIV_ZERO ) mask |= kDivByZero;
921  if (oldmask & _MM_MASK_OVERFLOW ) mask |= kOverflow;
922  if (oldmask & _MM_MASK_UNDERFLOW) mask |= kUnderflow;
923  if (oldmask & _MM_MASK_INEXACT ) mask |= kInexact;
924 #endif
925 
926 #if defined(R__MACOSX) && !defined(__SSE2__) && \
927  (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__arm64__))
928  fenv_t oldenv;
929  fegetenv(&oldenv);
930  fesetenv(&oldenv);
931 #if defined(__arm__)
932  Int_t oldmask = ~oldenv.__fpscr;
933 #elif defined(__arm64__)
934  Int_t oldmask = ~oldenv.__fpcr;
935 #else
936  Int_t oldmask = ~oldenv.__control;
937 #endif
938 
939  if (oldmask & FE_INVALID ) mask |= kInvalid;
940  if (oldmask & FE_DIVBYZERO) mask |= kDivByZero;
941  if (oldmask & FE_OVERFLOW ) mask |= kOverflow;
942  if (oldmask & FE_UNDERFLOW) mask |= kUnderflow;
943  if (oldmask & FE_INEXACT ) mask |= kInexact;
944 #endif
945 
946 #if defined(R__MACOSX) && !defined(__SSE2__) && !defined(__xlC__) && \
947  !defined(__i386__) && !defined(__x86_64__) && !defined(__arm__) && \
948  !defined(__arm64__)
949  Long64_t oldmask;
950  fegetenvd(oldmask);
951 
952  if (oldmask & FE_ENABLE_INVALID ) mask |= kInvalid;
953  if (oldmask & FE_ENABLE_DIVBYZERO) mask |= kDivByZero;
954  if (oldmask & FE_ENABLE_OVERFLOW ) mask |= kOverflow;
955  if (oldmask & FE_ENABLE_UNDERFLOW) mask |= kUnderflow;
956  if (oldmask & FE_ENABLE_INEXACT ) mask |= kInexact;
957 #endif
958 
959  return mask;
960 }
961 
962 ////////////////////////////////////////////////////////////////////////////////
963 /// Set which conditions trigger a floating point exception.
964 /// Return the previous set of conditions.
965 
967 {
968  if (mask) { } // use mask to avoid warning
969 
970  Int_t old = GetFPEMask();
971 
972 #if defined(R__LINUX) && !defined(__powerpc__)
973 #if defined(__GLIBC__) && (__GLIBC__>2 || __GLIBC__==2 && __GLIBC_MINOR__>=1)
974  Int_t newm = 0;
975  if (mask & kInvalid ) newm |= FE_INVALID;
976  if (mask & kDivByZero) newm |= FE_DIVBYZERO;
977  if (mask & kOverflow ) newm |= FE_OVERFLOW;
978  if (mask & kUnderflow) newm |= FE_UNDERFLOW;
979 # ifdef FE_INEXACT
980  if (mask & kInexact ) newm |= FE_INEXACT;
981 # endif
982 
983 #if __GLIBC_MINOR__>=3
984 
985  // clear pending exceptions so feenableexcept does not trigger them
986  feclearexcept(FE_ALL_EXCEPT);
987  fedisableexcept(FE_ALL_EXCEPT);
988  feenableexcept(newm);
989 
990 #else
991 
992  fenv_t cur;
993  fegetenv(&cur);
994 #if defined __ia64__
995  cur &= ~newm;
996 #else
997  cur.__control_word &= ~newm;
998 #endif
999  fesetenv(&cur);
1000 
1001 #endif
1002 #endif
1003 #endif
1004 
1005 #if defined(R__MACOSX) && defined(__SSE2__)
1006  // OS X uses the SSE unit for all FP math by default, not the x87 FP unit
1007  Int_t newm = 0;
1008  if (mask & kInvalid ) newm |= _MM_MASK_INVALID;
1009  if (mask & kDivByZero) newm |= _MM_MASK_DIV_ZERO;
1010  if (mask & kOverflow ) newm |= _MM_MASK_OVERFLOW;
1011  if (mask & kUnderflow) newm |= _MM_MASK_UNDERFLOW;
1012  if (mask & kInexact ) newm |= _MM_MASK_INEXACT;
1013 
1014  _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~newm);
1015 #endif
1016 
1017 #if defined(R__MACOSX) && !defined(__SSE2__) && \
1018  (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__arm64__))
1019  Int_t newm = 0;
1020  if (mask & kInvalid ) newm |= FE_INVALID;
1021  if (mask & kDivByZero) newm |= FE_DIVBYZERO;
1022  if (mask & kOverflow ) newm |= FE_OVERFLOW;
1023  if (mask & kUnderflow) newm |= FE_UNDERFLOW;
1024  if (mask & kInexact ) newm |= FE_INEXACT;
1025 
1026  fenv_t cur;
1027  fegetenv(&cur);
1028 #if defined(__arm__)
1029  cur.__fpscr &= ~newm;
1030 #elif defined(__arm64__)
1031  cur.__fpcr &= ~newm;
1032 #else
1033  cur.__control &= ~newm;
1034 #endif
1035  fesetenv(&cur);
1036 #endif
1037 
1038 #if defined(R__MACOSX) && !defined(__SSE2__) && !defined(__xlC__) && \
1039  !defined(__i386__) && !defined(__x86_64__) && !defined(__arm__) && \
1040  !defined(__arm64__)
1041  Int_t newm = 0;
1042  if (mask & kInvalid ) newm |= FE_ENABLE_INVALID;
1043  if (mask & kDivByZero) newm |= FE_ENABLE_DIVBYZERO;
1044  if (mask & kOverflow ) newm |= FE_ENABLE_OVERFLOW;
1045  if (mask & kUnderflow) newm |= FE_ENABLE_UNDERFLOW;
1046  if (mask & kInexact ) newm |= FE_ENABLE_INEXACT;
1047 
1048  Long64_t curmask;
1049  fegetenvd(curmask);
1050  curmask = (curmask & ~FE_ENABLE_ALL_EXCEPT) | newm;
1051  fesetenvd(curmask);
1052 #endif
1053 
1054  return old;
1055 }
1056 
1057 ////////////////////////////////////////////////////////////////////////////////
1058 /// Dispatch a single event.
1059 
1061 {
1062  Bool_t pollOnce = pendingOnly;
1063 
1064  while (1) {
1065  // first handle any X11 events
1066  if (gXDisplay && gXDisplay->Notify()) {
1067  if (fReadready->IsSet(gXDisplay->GetFd())) {
1068  fReadready->Clr(gXDisplay->GetFd());
1069  fNfd--;
1070  }
1071  if (!pendingOnly) return;
1072  }
1073 
1074  // check for file descriptors ready for reading/writing
1075  if (fNfd > 0 && fFileHandler && fFileHandler->GetSize() > 0)
1076  if (CheckDescriptors())
1077  if (!pendingOnly) return;
1078  fNfd = 0;
1079  fReadready->Zero();
1080  fWriteready->Zero();
1081 
1082  if (pendingOnly && !pollOnce)
1083  return;
1084 
1085  // check synchronous signals
1086  if (fSigcnt > 0 && fSignalHandler->GetSize() > 0)
1087  if (CheckSignals(kTRUE))
1088  if (!pendingOnly) return;
1089  fSigcnt = 0;
1090  fSignals->Zero();
1091 
1092  // check synchronous timers
1093  Long_t nextto;
1094  if (fTimers && fTimers->GetSize() > 0)
1095  if (DispatchTimers(kTRUE)) {
1096  // prevent timers from blocking file descriptor monitoring
1097  nextto = NextTimeOut(kTRUE);
1098  if (nextto > kItimerResolution || nextto == -1)
1099  return;
1100  }
1101 
1102  // if in pendingOnly mode poll once file descriptor activity
1103  nextto = NextTimeOut(kTRUE);
1104  if (pendingOnly) {
1105  if (fFileHandler && fFileHandler->GetSize() == 0)
1106  return;
1107  nextto = 0;
1108  pollOnce = kFALSE;
1109  }
1110 
1111  // nothing ready, so setup select call
1112  *fReadready = *fReadmask;
1113  *fWriteready = *fWritemask;
1114 
1115  int mxfd = TMath::Max(fMaxrfd, fMaxwfd);
1116  mxfd++;
1117 
1118  // if nothing to select (socket or timer) return
1119  if (mxfd == 0 && nextto == -1)
1120  return;
1121 
1122  fNfd = UnixSelect(mxfd, fReadready, fWriteready, nextto);
1123  if (fNfd < 0 && fNfd != -2) {
1124  int fd, rc;
1125  TFdSet t;
1126  for (fd = 0; fd < mxfd; fd++) {
1127  t.Set(fd);
1128  if (fReadmask->IsSet(fd)) {
1129  rc = UnixSelect(fd+1, &t, 0, 0);
1130  if (rc < 0 && rc != -2) {
1131  SysError("DispatchOneEvent", "select: read error on %d", fd);
1132  fReadmask->Clr(fd);
1133  }
1134  }
1135  if (fWritemask->IsSet(fd)) {
1136  rc = UnixSelect(fd+1, 0, &t, 0);
1137  if (rc < 0 && rc != -2) {
1138  SysError("DispatchOneEvent", "select: write error on %d", fd);
1139  fWritemask->Clr(fd);
1140  }
1141  }
1142  t.Clr(fd);
1143  }
1144  }
1145  }
1146 }
1147 
1148 ////////////////////////////////////////////////////////////////////////////////
1149 /// Sleep milliSec milliseconds.
1150 
1152 {
1153  struct timeval tv;
1154 
1155  tv.tv_sec = milliSec / 1000;
1156  tv.tv_usec = (milliSec % 1000) * 1000;
1157 
1158  select(0, 0, 0, 0, &tv);
1159 }
1160 
1161 ////////////////////////////////////////////////////////////////////////////////
1162 /// Select on file descriptors. The timeout to is in millisec. Returns
1163 /// the number of ready descriptors, or 0 in case of timeout, or < 0 in
1164 /// case of an error, with -2 being EINTR and -3 EBADF. In case of EINTR
1165 /// the errno has been reset and the method can be called again. Returns
1166 /// -4 in case the list did not contain any file handlers or file handlers
1167 /// with file descriptor >= 0.
1168 
1170 {
1171  Int_t rc = -4;
1172 
1173  TFdSet rd, wr;
1174  Int_t mxfd = -1;
1175  TIter next(act);
1176  TFileHandler *h = 0;
1177  while ((h = (TFileHandler *) next())) {
1178  Int_t fd = h->GetFd();
1179  if (fd > -1) {
1180  if (h->HasReadInterest()) {
1181  rd.Set(fd);
1182  mxfd = TMath::Max(mxfd, fd);
1183  }
1184  if (h->HasWriteInterest()) {
1185  wr.Set(fd);
1186  mxfd = TMath::Max(mxfd, fd);
1187  }
1188  h->ResetReadyMask();
1189  }
1190  }
1191  if (mxfd > -1)
1192  rc = UnixSelect(mxfd+1, &rd, &wr, to);
1193 
1194  // Set readiness bits
1195  if (rc > 0) {
1196  next.Reset();
1197  while ((h = (TFileHandler *) next())) {
1198  Int_t fd = h->GetFd();
1199  if (rd.IsSet(fd))
1200  h->SetReadReady();
1201  if (wr.IsSet(fd))
1202  h->SetWriteReady();
1203  }
1204  }
1205 
1206  return rc;
1207 }
1208 
1209 ////////////////////////////////////////////////////////////////////////////////
1210 /// Select on the file descriptor related to file handler h.
1211 /// The timeout to is in millisec. Returns the number of ready descriptors,
1212 /// or 0 in case of timeout, or < 0 in case of an error, with -2 being EINTR
1213 /// and -3 EBADF. In case of EINTR the errno has been reset and the method
1214 /// can be called again. Returns -4 in case the file handler is 0 or does
1215 /// not have a file descriptor >= 0.
1216 
1218 {
1219  Int_t rc = -4;
1220 
1221  TFdSet rd, wr;
1222  Int_t mxfd = -1;
1223  Int_t fd = -1;
1224  if (h) {
1225  fd = h->GetFd();
1226  if (fd > -1) {
1227  if (h->HasReadInterest())
1228  rd.Set(fd);
1229  if (h->HasWriteInterest())
1230  wr.Set(fd);
1231  h->ResetReadyMask();
1232  mxfd = fd;
1233  rc = UnixSelect(mxfd+1, &rd, &wr, to);
1234  }
1235  }
1236 
1237  // Fill output lists, if required
1238  if (rc > 0) {
1239  if (rd.IsSet(fd))
1240  h->SetReadReady();
1241  if (wr.IsSet(fd))
1242  h->SetWriteReady();
1243  }
1244 
1245  return rc;
1246 }
1247 
1248 //---- handling of system events -----------------------------------------------
1249 
1250 ////////////////////////////////////////////////////////////////////////////////
1251 /// Check if some signals were raised and call their Notify() member.
1252 
1254 {
1255  TSignalHandler *sh;
1256  Int_t sigdone = -1;
1257  {
1258  TOrdCollectionIter it((TOrdCollection*)fSignalHandler);
1259 
1260  while ((sh = (TSignalHandler*)it.Next())) {
1261  if (sync == sh->IsSync()) {
1262  ESignals sig = sh->GetSignal();
1263  if ((fSignals->IsSet(sig) && sigdone == -1) || sigdone == sig) {
1264  if (sigdone == -1) {
1265  fSignals->Clr(sig);
1266  sigdone = sig;
1267  fSigcnt--;
1268  }
1269  if (sh->IsActive())
1270  sh->Notify();
1271  }
1272  }
1273  }
1274  }
1275  if (sigdone != -1)
1276  return kTRUE;
1277 
1278  return kFALSE;
1279 }
1280 
1281 ////////////////////////////////////////////////////////////////////////////////
1282 /// Check if children have finished.
1283 
1285 {
1286 #if 0 //rdm
1287  int pid;
1288  while ((pid = UnixWaitchild()) > 0) {
1289  TIter next(zombieHandler);
1290  register UnixPtty *pty;
1291  while ((pty = (UnixPtty*) next()))
1292  if (pty->GetPid() == pid) {
1293  zombieHandler->RemovePtr(pty);
1294  pty->DiedNotify();
1295  }
1296  }
1297 #endif
1298 }
1299 
1300 ////////////////////////////////////////////////////////////////////////////////
1301 /// Check if there is activity on some file descriptors and call their
1302 /// Notify() member.
1303 
1305 {
1306  TFileHandler *fh;
1307  Int_t fddone = -1;
1308  Bool_t read = kFALSE;
1309  TOrdCollectionIter it((TOrdCollection*)fFileHandler);
1310  while ((fh = (TFileHandler*) it.Next())) {
1311  Int_t fd = fh->GetFd();
1312  if ((fd <= fMaxrfd && fReadready->IsSet(fd) && fddone == -1) ||
1313  (fddone == fd && read)) {
1314  if (fddone == -1) {
1315  fReadready->Clr(fd);
1316  fddone = fd;
1317  read = kTRUE;
1318  fNfd--;
1319  }
1320  if (fh->IsActive())
1321  fh->ReadNotify();
1322  }
1323  if ((fd <= fMaxwfd && fWriteready->IsSet(fd) && fddone == -1) ||
1324  (fddone == fd && !read)) {
1325  if (fddone == -1) {
1326  fWriteready->Clr(fd);
1327  fddone = fd;
1328  read = kFALSE;
1329  fNfd--;
1330  }
1331  if (fh->IsActive())
1332  fh->WriteNotify();
1333  }
1334  }
1335  if (fddone != -1)
1336  return kTRUE;
1337 
1338  return kFALSE;
1339 }
1340 
1341 //---- Directories -------------------------------------------------------------
1342 
1343 ////////////////////////////////////////////////////////////////////////////////
1344 /// Make a Unix file system directory. Returns 0 in case of success and
1345 /// -1 if the directory could not be created.
1346 
1348 {
1349  TSystem *helper = FindHelper(name);
1350  if (helper)
1351  return helper->MakeDirectory(name);
1352 
1353  return UnixMakedir(name);
1354 }
1355 
1356 ////////////////////////////////////////////////////////////////////////////////
1357 /// Open a Unix file system directory. Returns 0 if directory does not exist.
1358 
1360 {
1361  TSystem *helper = FindHelper(name);
1362  if (helper)
1363  return helper->OpenDirectory(name);
1364 
1365  return UnixOpendir(name);
1366 }
1367 
1368 ////////////////////////////////////////////////////////////////////////////////
1369 /// Close a Unix file system directory.
1370 
1372 {
1373  TSystem *helper = FindHelper(0, dirp);
1374  if (helper) {
1375  helper->FreeDirectory(dirp);
1376  return;
1377  }
1378 
1379  if (dirp)
1380  ::closedir((DIR*)dirp);
1381 }
1382 
1383 ////////////////////////////////////////////////////////////////////////////////
1384 /// Get next Unix file system directory entry. Returns 0 if no more entries.
1385 
1386 const char *TUnixSystem::GetDirEntry(void *dirp)
1387 {
1388  TSystem *helper = FindHelper(0, dirp);
1389  if (helper)
1390  return helper->GetDirEntry(dirp);
1391 
1392  if (dirp)
1393  return UnixGetdirentry(dirp);
1394 
1395  return 0;
1396 }
1397 
1398 ////////////////////////////////////////////////////////////////////////////////
1399 /// Change directory. Returns kTRUE in case of success, kFALSE otherwise.
1400 
1402 {
1403  Bool_t ret = (Bool_t) (::chdir(path) == 0);
1404  if (fWdpath != "")
1405  fWdpath = ""; // invalidate path cache
1406  return ret;
1407 }
1408 
1409 ////////////////////////////////////////////////////////////////////////////////
1410 /// Return working directory.
1411 
1413 {
1414  // don't use cache as user can call chdir() directly somewhere else
1415  //if (fWdpath != "")
1416  // return fWdpath.Data();
1417 
1419 
1420  static char cwd[kMAXPATHLEN];
1421  FillWithCwd(cwd);
1422  fWdpath = cwd;
1423 
1424  return fWdpath.Data();
1425 }
1426 
1427 //////////////////////////////////////////////////////////////////////////////
1428 /// Return working directory.
1429 
1431 {
1432  char cwd[kMAXPATHLEN];
1433  FillWithCwd(cwd);
1434  return std::string(cwd);
1435 }
1436 
1437 //////////////////////////////////////////////////////////////////////////////
1438 /// Fill buffer with current working directory.
1439 
1440 void TUnixSystem::FillWithCwd(char *cwd) const
1441 {
1442  if (::getcwd(cwd, kMAXPATHLEN) == 0) {
1443  Error("WorkingDirectory", "getcwd() failed");
1444  }
1445 }
1446 
1447 ////////////////////////////////////////////////////////////////////////////////
1448 /// Return the user's home directory.
1449 
1450 const char *TUnixSystem::HomeDirectory(const char *userName)
1451 {
1452  return UnixHomedirectory(userName);
1453 }
1454 
1455 //////////////////////////////////////////////////////////////////////////////
1456 /// Return the user's home directory.
1457 
1458 std::string TUnixSystem::GetHomeDirectory(const char *userName) const
1459 {
1460  char path[kMAXPATHLEN], mydir[kMAXPATHLEN] = { '\0' };
1461  return std::string(UnixHomedirectory(userName, path, mydir));
1462 }
1463 
1464 ////////////////////////////////////////////////////////////////////////////////
1465 /// Return a user configured or systemwide directory to create
1466 /// temporary files in.
1467 
1468 const char *TUnixSystem::TempDirectory() const
1469 {
1470  const char *dir = gSystem->Getenv("TMPDIR");
1471  if (!dir || gSystem->AccessPathName(dir, kWritePermission))
1472  dir = "/tmp";
1473 
1474  return dir;
1475 }
1476 
1477 ////////////////////////////////////////////////////////////////////////////////
1478 /// Create a secure temporary file by appending a unique
1479 /// 6 letter string to base. The file will be created in
1480 /// a standard (system) directory or in the directory
1481 /// provided in dir. The full filename is returned in base
1482 /// and a filepointer is returned for safely writing to the file
1483 /// (this avoids certain security problems). Returns 0 in case
1484 /// of error.
1485 
1486 FILE *TUnixSystem::TempFileName(TString &base, const char *dir)
1487 {
1488  char *b = ConcatFileName(dir ? dir : TempDirectory(), base);
1489  base = b;
1490  base += "XXXXXX";
1491  delete [] b;
1492 
1493  char *arg = StrDup(base);
1494  int fd = mkstemp(arg);
1495  base = arg;
1496  delete [] arg;
1497 
1498  if (fd == -1) {
1499  SysError("TempFileName", "%s", base.Data());
1500  return 0;
1501  } else {
1502  FILE *fp = fdopen(fd, "w+");
1503  if (fp == 0)
1504  SysError("TempFileName", "converting filedescriptor (%d)", fd);
1505  return fp;
1506  }
1507 }
1508 
1509 ////////////////////////////////////////////////////////////////////////////////
1510 /// Concatenate a directory and a file name.
1511 
1512 const char *TUnixSystem::PrependPathName(const char *dir, TString& name)
1513 {
1514  if (name.IsNull() || name == ".") {
1515  if (dir) {
1516  name = dir;
1517  if (dir[strlen(dir) - 1] != '/')
1518  name += '/';
1519  } else name = "";
1520  return name.Data();
1521  }
1522 
1523  if (!dir || !dir[0]) dir = "/";
1524  else if (dir[strlen(dir) - 1] != '/')
1525  name.Prepend('/');
1526  name.Prepend(dir);
1527 
1528  return name.Data();
1529 }
1530 
1531 //---- Paths & Files -----------------------------------------------------------
1532 
1533 ////////////////////////////////////////////////////////////////////////////////
1534 /// Returns FALSE if one can access a file using the specified access mode.
1535 /// Mode is the same as for the Unix access(2) function.
1536 /// Attention, bizarre convention of return value!!
1537 
1539 {
1540  TSystem *helper = FindHelper(path);
1541  if (helper)
1542  return helper->AccessPathName(path, mode);
1543 
1544  if (::access(StripOffProto(path, "file:"), mode) == 0)
1545  return kFALSE;
1546  GetLastErrorString() = GetError();
1547 
1548  return kTRUE;
1549 }
1550 
1551 ////////////////////////////////////////////////////////////////////////////////
1552 /// Copy a file. If overwrite is true and file already exists the
1553 /// file will be overwritten. Returns 0 when successful, -1 in case
1554 /// of file open failure, -2 in case the file already exists and overwrite
1555 /// was false and -3 in case of error during copy.
1556 
1557 int TUnixSystem::CopyFile(const char *f, const char *t, Bool_t overwrite)
1558 {
1559  if (!AccessPathName(t) && !overwrite)
1560  return -2;
1561 
1562  FILE *from = fopen(f, "r");
1563  if (!from)
1564  return -1;
1565 
1566  FILE *to = fopen(t, "w");
1567  if (!to) {
1568  fclose(from);
1569  return -1;
1570  }
1571 
1572  const int bufsize = 1024;
1573  char buf[bufsize];
1574  int ret = 0;
1575  while (!ret && !feof(from)) {
1576  size_t numread = fread (buf, sizeof(char), bufsize, from);
1577  size_t numwritten = fwrite(buf, sizeof(char), numread, to);
1578  if (numread != numwritten)
1579  ret = -3;
1580  }
1581 
1582  fclose(from);
1583  fclose(to);
1584 
1585  return ret;
1586 }
1587 
1588 ////////////////////////////////////////////////////////////////////////////////
1589 /// Rename a file. Returns 0 when successful, -1 in case of failure.
1590 
1591 int TUnixSystem::Rename(const char *f, const char *t)
1592 {
1593  int ret = ::rename(f, t);
1594  GetLastErrorString() = GetError();
1595  return ret;
1596 }
1597 
1598 ////////////////////////////////////////////////////////////////////////////////
1599 /// Returns TRUE if the url in 'path' points to the local file system.
1600 /// This is used to avoid going through the NIC card for local operations.
1601 
1603 {
1604  TSystem *helper = FindHelper(path);
1605  if (helper)
1606  return helper->IsPathLocal(path);
1607 
1608  return TSystem::IsPathLocal(path);
1609 }
1610 
1611 ////////////////////////////////////////////////////////////////////////////////
1612 /// Get info about a file. Info is returned in the form of a FileStat_t
1613 /// structure (see TSystem.h).
1614 /// The function returns 0 in case of success and 1 if the file could
1615 /// not be stat'ed.
1616 
1617 int TUnixSystem::GetPathInfo(const char *path, FileStat_t &buf)
1618 {
1619  TSystem *helper = FindHelper(path);
1620  if (helper)
1621  return helper->GetPathInfo(path, buf);
1622 
1623  return UnixFilestat(path, buf);
1624 }
1625 
1626 ////////////////////////////////////////////////////////////////////////////////
1627 /// Get info about a file system: id, bsize, bfree, blocks.
1628 /// Id is file system type (machine dependend, see statfs())
1629 /// Bsize is block size of file system
1630 /// Blocks is total number of blocks in file system
1631 /// Bfree is number of free blocks in file system
1632 /// The function returns 0 in case of success and 1 if the file system could
1633 /// not be stat'ed.
1634 
1635 int TUnixSystem::GetFsInfo(const char *path, Long_t *id, Long_t *bsize,
1636  Long_t *blocks, Long_t *bfree)
1637 {
1638  return UnixFSstat(path, id, bsize, blocks, bfree);
1639 }
1640 
1641 ////////////////////////////////////////////////////////////////////////////////
1642 /// Create a link from file1 to file2. Returns 0 when successful,
1643 /// -1 in case of failure.
1644 
1645 int TUnixSystem::Link(const char *from, const char *to)
1646 {
1647  return ::link(from, to);
1648 }
1649 
1650 ////////////////////////////////////////////////////////////////////////////////
1651 /// Create a symlink from file1 to file2. Returns 0 when successful,
1652 /// -1 in case of failure.
1653 
1654 int TUnixSystem::Symlink(const char *from, const char *to)
1655 {
1656 #if defined(R__AIX)
1657  return ::symlink((char*)from, (char*)to);
1658 #else
1659  return ::symlink(from, to);
1660 #endif
1661 }
1662 
1663 ////////////////////////////////////////////////////////////////////////////////
1664 /// Unlink, i.e. remove, a file or directory. Returns 0 when successful,
1665 /// -1 in case of failure.
1666 
1667 int TUnixSystem::Unlink(const char *name)
1668 {
1669  TSystem *helper = FindHelper(name);
1670  if (helper)
1671  return helper->Unlink(name);
1672 
1673 #if defined(R__SEEK64)
1674  struct stat64 finfo;
1675  if (lstat64(name, &finfo) < 0)
1676 #else
1677  struct stat finfo;
1678  if (lstat(name, &finfo) < 0)
1679 #endif
1680  return -1;
1681 
1682  if (S_ISDIR(finfo.st_mode))
1683  return ::rmdir(name);
1684  else
1685  return ::unlink(name);
1686 }
1687 
1688 //---- expand the metacharacters as in the shell -------------------------------
1689 
1690 // expand the metacharacters as in the shell
1691 
1692 const char
1693 #ifdef G__OLDEXPAND
1694  kShellEscape = '\\',
1695  *kShellStuff = "(){}<>\"'",
1696 #endif
1697  *kShellMeta = "~*[]{}?$";
1698 
1699 
1700 #ifndef G__OLDEXPAND
1701 ////////////////////////////////////////////////////////////////////////////////
1702 /// Expand a pathname getting rid of special shell characters like ~.$, etc.
1703 /// For Unix/Win32 compatibility use $(XXX) instead of $XXX when using
1704 /// environment variables in a pathname. If compatibility is not an issue
1705 /// you can use on Unix directly $XXX. Returns kFALSE in case of success
1706 /// or kTRUE in case of error.
1707 
1709 {
1710  const char *p, *patbuf = (const char *)path;
1711 
1712  // skip leading blanks
1713  while (*patbuf == ' ')
1714  patbuf++;
1715 
1716  // any shell meta characters ?
1717  for (p = patbuf; *p; p++)
1718  if (strchr(kShellMeta, *p))
1719  goto expand;
1720 
1721  return kFALSE;
1722 
1723 expand:
1724  // replace $(XXX) by $XXX
1725  path.ReplaceAll("$(","$");
1726  path.ReplaceAll(")","");
1727 
1728  return ExpandFileName(path);
1729 }
1730 #endif
1731 
1732 #ifdef G__OLDEXPAND
1733 ////////////////////////////////////////////////////////////////////////////////
1734 /// Expand a pathname getting rid of special shell characters like ~.$, etc.
1735 /// For Unix/Win32 compatibility use $(XXX) instead of $XXX when using
1736 /// environment variables in a pathname. If compatibility is not an issue
1737 /// you can use on Unix directly $XXX. Returns kFALSE in case of success
1738 /// or kTRUE in case of error.
1739 
1741 {
1742  const char *patbuf = (const char *)patbuf0;
1743  const char *hd, *p;
1744  // char cmd[kMAXPATHLEN],
1745  char stuffedPat[kMAXPATHLEN], name[70];
1746  char *q;
1747  FILE *pf;
1748  int ch;
1749 
1750  // skip leading blanks
1751  while (*patbuf == ' ')
1752  patbuf++;
1753 
1754  // any shell meta characters ?
1755  for (p = patbuf; *p; p++)
1756  if (strchr(kShellMeta, *p))
1757  goto needshell;
1758 
1759  return kFALSE;
1760 
1761 needshell:
1762  // replace $(XXX) by $XXX
1763  patbuf0.ReplaceAll("$(","$");
1764  patbuf0.ReplaceAll(")","");
1765 
1766  // escape shell quote characters
1767  EscChar(patbuf, stuffedPat, sizeof(stuffedPat), (char*)kShellStuff, kShellEscape);
1768 
1769  TString cmd("echo ");
1770 
1771  // emulate csh -> popen executes sh
1772  if (stuffedPat[0] == '~') {
1773  if (stuffedPat[1] != '\0' && stuffedPat[1] != '/') {
1774  // extract user name
1775  for (p = &stuffedPat[1], q = name; *p && *p !='/';)
1776  *q++ = *p++;
1777  *q = '\0';
1778  hd = UnixHomedirectory(name);
1779  if (hd == 0)
1780  cmd += stuffedPat;
1781  else {
1782  cmd += hd;
1783  cmd += p;
1784  }
1785  } else {
1786  hd = UnixHomedirectory(0);
1787  if (hd == 0) {
1788  GetLastErrorString() = GetError();
1789  return kTRUE;
1790  }
1791  cmd += hd;
1792  cmd += &stuffedPat[1];
1793  }
1794  } else
1795  cmd += stuffedPat;
1796 
1797  if ((pf = ::popen(cmd.Data(), "r")) == 0) {
1798  GetLastErrorString() = GetError();
1799  return kTRUE;
1800  }
1801 
1802  // read first argument
1803  patbuf0 = "";
1804  int cnt = 0;
1805 #if defined(R__AIX)
1806 again:
1807 #endif
1808  for (ch = fgetc(pf); ch != EOF && ch != ' ' && ch != '\n'; ch = fgetc(pf)) {
1809  patbuf0.Append(ch);
1810  cnt++;
1811  }
1812 #if defined(R__AIX)
1813  // Work around bug timing problem due to delay in forking a large program
1814  if (cnt == 0 && ch == EOF) goto again;
1815 #endif
1816 
1817  // skip rest of pipe
1818  while (ch != EOF) {
1819  ch = fgetc(pf);
1820  if (ch == ' ' || ch == '\t') {
1821  GetLastErrorString() = "expression ambigous";
1822  ::pclose(pf);
1823  return kTRUE;
1824  }
1825  }
1826 
1827  ::pclose(pf);
1828 
1829  return kFALSE;
1830 }
1831 #endif
1832 
1833 ////////////////////////////////////////////////////////////////////////////////
1834 /// Expand a pathname getting rid of special shell characaters like ~.$, etc.
1835 /// For Unix/Win32 compatibility use $(XXX) instead of $XXX when using
1836 /// environment variables in a pathname. If compatibility is not an issue
1837 /// you can use on Unix directly $XXX. The user must delete returned string.
1838 /// Returns the expanded pathname or 0 in case of error.
1839 /// The user must delete returned string (delete []).
1840 
1841 char *TUnixSystem::ExpandPathName(const char *path)
1842 {
1843  TString patbuf = path;
1844  if (ExpandPathName(patbuf))
1845  return 0;
1846  return StrDup(patbuf.Data());
1847 }
1848 
1849 ////////////////////////////////////////////////////////////////////////////////
1850 /// Set the file permission bits. Returns -1 in case or error, 0 otherwise.
1851 
1852 int TUnixSystem::Chmod(const char *file, UInt_t mode)
1853 {
1854  return ::chmod(file, mode);
1855 }
1856 
1857 ////////////////////////////////////////////////////////////////////////////////
1858 /// Set the process file creation mode mask.
1859 
1861 {
1862  return ::umask(mask);
1863 }
1864 
1865 ////////////////////////////////////////////////////////////////////////////////
1866 /// Set a files modification and access times. If actime = 0 it will be
1867 /// set to the modtime. Returns 0 on success and -1 in case of error.
1868 
1869 int TUnixSystem::Utime(const char *file, Long_t modtime, Long_t actime)
1870 {
1871  if (!actime)
1872  actime = modtime;
1873 
1874  struct utimbuf t;
1875  t.actime = (time_t)actime;
1876  t.modtime = (time_t)modtime;
1877  return ::utime(file, &t);
1878 }
1879 
1880 ////////////////////////////////////////////////////////////////////////////////
1881 /// Find location of file "wfil" in a search path.
1882 /// The search path is specified as a : separated list of directories.
1883 /// Return value is pointing to wfile for compatibility with
1884 /// Which(const char*,const char*,EAccessMode) version.
1885 
1886 const char *TUnixSystem::FindFile(const char *search, TString& wfil, EAccessMode mode)
1887 {
1888  TString show;
1889  if (gEnv->GetValue("Root.ShowPath", 0))
1890  show.Form("Which: %s =", wfil.Data());
1891 
1892  gSystem->ExpandPathName(wfil);
1893 
1894  if (wfil[0] == '/') {
1895 #if defined(R__SEEK64)
1896  struct stat64 finfo;
1897  if (access(wfil.Data(), mode) == 0 &&
1898  stat64(wfil.Data(), &finfo) == 0 && S_ISREG(finfo.st_mode)) {
1899 #else
1900  struct stat finfo;
1901  if (access(wfil.Data(), mode) == 0 &&
1902  stat(wfil.Data(), &finfo) == 0 && S_ISREG(finfo.st_mode)) {
1903 #endif
1904  if (show != "")
1905  Printf("%s %s", show.Data(), wfil.Data());
1906  return wfil.Data();
1907  }
1908  if (show != "")
1909  Printf("%s <not found>", show.Data());
1910  wfil = "";
1911  return 0;
1912  }
1913 
1914  if (search == 0)
1915  search = ".";
1916 
1917  TString apwd(gSystem->WorkingDirectory());
1918  apwd += "/";
1919  for (const char* ptr = search; *ptr;) {
1920  TString name;
1921  if (*ptr != '/' && *ptr !='$' && *ptr != '~')
1922  name = apwd;
1923  const char* posEndOfPart = strchr(ptr, ':');
1924  if (posEndOfPart) {
1925  name.Append(ptr, posEndOfPart - ptr);
1926  ptr = posEndOfPart + 1; // skip ':'
1927  } else {
1928  name.Append(ptr);
1929  ptr += strlen(ptr);
1930  }
1931 
1932  if (!name.EndsWith("/"))
1933  name += '/';
1934  name += wfil;
1935 
1936  gSystem->ExpandPathName(name);
1937 #if defined(R__SEEK64)
1938  struct stat64 finfo;
1939  if (access(name.Data(), mode) == 0 &&
1940  stat64(name.Data(), &finfo) == 0 && S_ISREG(finfo.st_mode)) {
1941 #else
1942  struct stat finfo;
1943  if (access(name.Data(), mode) == 0 &&
1944  stat(name.Data(), &finfo) == 0 && S_ISREG(finfo.st_mode)) {
1945 #endif
1946  if (show != "")
1947  Printf("%s %s", show.Data(), name.Data());
1948  wfil = name;
1949  return wfil.Data();
1950  }
1951  }
1952 
1953  if (show != "")
1954  Printf("%s <not found>", show.Data());
1955  wfil = "";
1956  return 0;
1957 }
1958 
1959 //---- Users & Groups ----------------------------------------------------------
1960 
1961 ////////////////////////////////////////////////////////////////////////////////
1962 /// Returns the user's id. If user = 0, returns current user's id.
1963 
1964 Int_t TUnixSystem::GetUid(const char *user)
1965 {
1966  if (!user || !user[0])
1967  return getuid();
1968  else {
1969  struct passwd *apwd = getpwnam(user);
1970  if (apwd)
1971  return apwd->pw_uid;
1972  }
1973  return 0;
1974 }
1975 
1976 ////////////////////////////////////////////////////////////////////////////////
1977 /// Returns the effective user id. The effective id corresponds to the
1978 /// set id bit on the file being executed.
1979 
1981 {
1982  return geteuid();
1983 }
1984 
1985 ////////////////////////////////////////////////////////////////////////////////
1986 /// Returns the group's id. If group = 0, returns current user's group.
1987 
1989 {
1990  if (!group || !group[0])
1991  return getgid();
1992  else {
1993  struct group *grp = getgrnam(group);
1994  if (grp)
1995  return grp->gr_gid;
1996  }
1997  return 0;
1998 }
1999 
2000 ////////////////////////////////////////////////////////////////////////////////
2001 /// Returns the effective group id. The effective group id corresponds
2002 /// to the set id bit on the file being executed.
2003 
2005 {
2006  return getegid();
2007 }
2008 
2009 ////////////////////////////////////////////////////////////////////////////////
2010 /// Returns all user info in the UserGroup_t structure. The returned
2011 /// structure must be deleted by the user. In case of error 0 is returned.
2012 
2014 {
2015  typedef std::map<Int_t /*uid*/, UserGroup_t> UserInfoCache_t;
2016  static UserInfoCache_t gUserInfo;
2017 
2018  UserInfoCache_t::const_iterator iUserInfo = gUserInfo.find(uid);
2019  if (iUserInfo != gUserInfo.end())
2020  return new UserGroup_t(iUserInfo->second);
2021 
2022  struct passwd *apwd = getpwuid(uid);
2023  if (apwd) {
2024  UserGroup_t *ug = new UserGroup_t;
2025  ug->fUid = apwd->pw_uid;
2026  ug->fGid = apwd->pw_gid;
2027  ug->fUser = apwd->pw_name;
2028  ug->fPasswd = apwd->pw_passwd;
2029  ug->fRealName = apwd->pw_gecos;
2030  ug->fShell = apwd->pw_shell;
2031  UserGroup_t *gr = GetGroupInfo(apwd->pw_gid);
2032  if (gr) ug->fGroup = gr->fGroup;
2033  delete gr;
2034 
2035  gUserInfo[uid] = *ug;
2036  return ug;
2037  }
2038  return 0;
2039 }
2040 
2041 ////////////////////////////////////////////////////////////////////////////////
2042 /// Returns all user info in the UserGroup_t structure. If user = 0, returns
2043 /// current user's id info. The returned structure must be deleted by the
2044 /// user. In case of error 0 is returned.
2045 
2047 {
2048  return GetUserInfo(GetUid(user));
2049 }
2050 
2051 ////////////////////////////////////////////////////////////////////////////////
2052 /// Returns all group info in the UserGroup_t structure. The only active
2053 /// fields in the UserGroup_t structure for this call are:
2054 /// fGid and fGroup
2055 /// The returned structure must be deleted by the user. In case of
2056 /// error 0 is returned.
2057 
2059 {
2060  struct group *grp = getgrgid(gid);
2061  if (grp) {
2062  UserGroup_t *gr = new UserGroup_t;
2063  gr->fUid = 0;
2064  gr->fGid = grp->gr_gid;
2065  gr->fGroup = grp->gr_name;
2066  return gr;
2067  }
2068  return 0;
2069 }
2070 
2071 ////////////////////////////////////////////////////////////////////////////////
2072 /// Returns all group info in the UserGroup_t structure. The only active
2073 /// fields in the UserGroup_t structure for this call are:
2074 /// fGid and fGroup
2075 /// If group = 0, returns current user's group. The returned structure
2076 /// must be deleted by the user. In case of error 0 is returned.
2077 
2079 {
2080  return GetGroupInfo(GetGid(group));
2081 }
2082 
2083 //---- environment manipulation ------------------------------------------------
2084 
2085 ////////////////////////////////////////////////////////////////////////////////
2086 /// Set environment variable.
2087 
2088 void TUnixSystem::Setenv(const char *name, const char *value)
2089 {
2090  ::setenv(name, value, 1);
2091 }
2092 
2093 ////////////////////////////////////////////////////////////////////////////////
2094 /// Get environment variable.
2095 
2096 const char *TUnixSystem::Getenv(const char *name)
2097 {
2098  return ::getenv(name);
2099 }
2100 
2101 ////////////////////////////////////////////////////////////////////////////////
2102 /// Unset environment variable.
2103 
2104 void TUnixSystem::Unsetenv(const char *name)
2105 {
2106  ::unsetenv(name);
2107 }
2108 
2109 //---- Processes ---------------------------------------------------------------
2110 
2111 ////////////////////////////////////////////////////////////////////////////////
2112 /// Execute a command.
2113 
2114 int TUnixSystem::Exec(const char *shellcmd)
2115 {
2116  return ::system(shellcmd);
2117 }
2118 
2119 ////////////////////////////////////////////////////////////////////////////////
2120 /// Open a pipe.
2121 
2122 FILE *TUnixSystem::OpenPipe(const char *command, const char *mode)
2123 {
2124  return ::popen(command, mode);
2125 }
2126 
2127 ////////////////////////////////////////////////////////////////////////////////
2128 /// Close the pipe.
2129 
2130 int TUnixSystem::ClosePipe(FILE *pipe)
2131 {
2132  return ::pclose(pipe);
2133 }
2134 
2135 ////////////////////////////////////////////////////////////////////////////////
2136 /// Get process id.
2137 
2139 {
2140  return ::getpid();
2141 }
2142 
2143 ////////////////////////////////////////////////////////////////////////////////
2144 /// Exit the application.
2145 
2146 void TUnixSystem::Exit(int code, Bool_t mode)
2147 {
2148  // Insures that the files and sockets are closed before any library is unloaded
2149  // and before emptying CINT.
2150  if (gROOT) {
2151  gROOT->EndOfProcessCleanups();
2152  } else if (gInterpreter) {
2153  gInterpreter->ResetGlobals();
2154  }
2155 
2156  if (mode)
2157  ::exit(code);
2158  else
2159  ::_exit(code);
2160 }
2161 
2162 ////////////////////////////////////////////////////////////////////////////////
2163 /// Abort the application.
2164 
2166 {
2167  ::abort();
2168 }
2169 
2170 
2171 #ifdef R__MACOSX
2172 /// Use CoreSymbolication to retrieve the stacktrace.
2173 #include <mach/mach.h>
2174 extern "C" {
2175  // Adapted from https://github.com/mountainstorm/CoreSymbolication
2176  // Under the hood the framework basically just calls through to a set of C++ libraries
2177  typedef struct {
2178  void* csCppData;
2179  void* csCppObj;
2180  } CSTypeRef;
2181  typedef CSTypeRef CSSymbolicatorRef;
2182  typedef CSTypeRef CSSourceInfoRef;
2183  typedef CSTypeRef CSSymbolOwnerRef;
2184  typedef CSTypeRef CSSymbolRef;
2185 
2186  CSSymbolicatorRef CSSymbolicatorCreateWithPid(pid_t pid);
2187  CSSourceInfoRef CSSymbolicatorGetSourceInfoWithAddressAtTime(CSSymbolicatorRef cs, vm_address_t addr, uint64_t time);
2188  CSSymbolRef CSSourceInfoGetSymbol(CSSourceInfoRef info);
2189  const char* CSSymbolGetName(CSSymbolRef sym);
2190  CSSymbolOwnerRef CSSourceInfoGetSymbolOwner(CSSourceInfoRef info);
2191  const char* CSSymbolOwnerGetPath(CSSymbolOwnerRef symbol);
2192  const char* CSSourceInfoGetPath(CSSourceInfoRef info);
2193  int CSSourceInfoGetLineNumber(CSSourceInfoRef info);
2194 }
2195 
2196 void macosx_backtrace() {
2197  void* addrlist[kMAX_BACKTRACE_DEPTH];
2198  // retrieve current stack addresses
2199  int numstacks = backtrace( addrlist, sizeof( addrlist ) / sizeof( void* ));
2200 
2201  CSSymbolicatorRef symbolicator = CSSymbolicatorCreateWithPid(getpid());
2202 
2203  // skip TUnixSystem::Backtrace(), macosx_backtrace()
2204  static const int skipFrames = 2;
2205  for (int i = skipFrames; i < numstacks; ++i) {
2206  CSSourceInfoRef sourceInfo
2207  = CSSymbolicatorGetSourceInfoWithAddressAtTime(symbolicator,
2208  (vm_address_t)addrlist[i],
2209  0x80000000u /*"now"*/);
2210 
2211  CSSymbolOwnerRef symOwner = CSSourceInfoGetSymbolOwner(sourceInfo);
2212  if (const char* libPath = CSSymbolOwnerGetPath(symOwner)) {
2213  printf("[%s]", libPath);
2214  } else {
2215  printf("[<unknown binary>]");
2216  }
2217 
2218  CSSymbolRef sym = CSSourceInfoGetSymbol(sourceInfo);
2219  if (const char* symname = CSSymbolGetName(sym)) {
2220  printf(" %s %s:%d", symname, CSSourceInfoGetPath(sourceInfo),
2221  (int)CSSourceInfoGetLineNumber(sourceInfo));
2222  }
2223  printf("\n");
2224  }
2225 }
2226 #endif // R__MACOSX
2227 
2228 ////////////////////////////////////////////////////////////////////////////////
2229 /// Print a stack trace.
2230 
2232 {
2233  if (!gEnv->GetValue("Root.Stacktrace", 1))
2234  return;
2235 
2236 #ifndef R__MACOSX
2237  TString gdbscript = gEnv->GetValue("Root.StacktraceScript", "");
2238  gdbscript = gdbscript.Strip();
2239  if (gdbscript != "") {
2240  if (AccessPathName(gdbscript, kReadPermission)) {
2241  fprintf(stderr, "Root.StacktraceScript %s does not exist\n", gdbscript.Data());
2242  gdbscript = "";
2243  } else {
2244  gdbscript += " ";
2245  }
2246  }
2247  if (gdbscript == "") {
2248 #ifdef ROOTETCDIR
2249  gdbscript.Form("%s/gdb-backtrace.sh", ROOTETCDIR);
2250 #else
2251  gdbscript.Form("%s/etc/gdb-backtrace.sh", Getenv("ROOTSYS"));
2252 #endif
2253  if (AccessPathName(gdbscript, kReadPermission)) {
2254  fprintf(stderr, "Error in <TUnixSystem::StackTrace> script %s is missing\n", gdbscript.Data());
2255  return;
2256  }
2257  gdbscript += " ";
2258  }
2259 
2260  TString gdbmess = gEnv->GetValue("Root.StacktraceMessage", "");
2261  gdbmess = gdbmess.Strip();
2262 
2263  std::cout.flush();
2264  fflush(stdout);
2265 
2266  std::cerr.flush();
2267  fflush(stderr);
2268 
2269  int fd = STDERR_FILENO;
2270 
2271  const char *message = " Generating stack trace...\n";
2272 
2273  if (fd && message) { } // remove unused warning (remove later)
2274 
2275  if (gApplication && !strcmp(gApplication->GetName(), "TRint"))
2276  Getlinem(kCleanUp, 0);
2277 
2278 #if defined(USE_GDB_STACK_TRACE)
2279  char *gdb = Which(Getenv("PATH"), "gdb", kExecutePermission);
2280  if (!gdb) {
2281  fprintf(stderr, "gdb not found, need it for stack trace\n");
2282  return;
2283  }
2284 
2285  // write custom message file
2286  TString gdbmessf = "gdb-message";
2287  if (gdbmess != "") {
2288  FILE *f = TempFileName(gdbmessf);
2289  fprintf(f, "%s\n", gdbmess.Data());
2290  fclose(f);
2291  }
2292 
2293  // use gdb to get stack trace
2294  gdbscript += GetExePath();
2295  gdbscript += " ";
2296  gdbscript += GetPid();
2297  if (gdbmess != "") {
2298  gdbscript += " ";
2299  gdbscript += gdbmessf;
2300  }
2301  gdbscript += " 1>&2";
2302  Exec(gdbscript);
2303  delete [] gdb;
2304  return;
2305 
2306 #elif defined(R__AIX)
2307  TString script = "procstack ";
2308  script += GetPid();
2309  Exec(script);
2310  return;
2311 #elif defined(R__SOLARIS)
2312  char *cppfilt = Which(Getenv("PATH"), "c++filt", kExecutePermission);
2313  TString script = "pstack ";
2314  script += GetPid();
2315  if (cppfilt) {
2316  script += " | ";
2317  script += cppfilt;
2318  delete [] cppfilt;
2319  }
2320  Exec(script);
2321  return;
2322 #elif defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_DLADDR) // linux + MacOS X >= 10.5
2323  // we could have used backtrace_symbols_fd, except its output
2324  // format is pretty bad, so recode that here :-(
2325 
2326  // take care of demangling
2327  Bool_t demangle = kTRUE;
2328 
2329  // check for c++filt
2330  const char *cppfilt = "c++filt";
2331  const char *cppfiltarg = "";
2332 #ifdef R__B64
2333  const char *format1 = " 0x%016lx in %.200s %s 0x%lx from %.200s\n";
2334 #ifdef R__MACOSX
2335  const char *format2 = " 0x%016lx in %.200s\n";
2336 #else
2337  const char *format2 = " 0x%016lx in %.200s at %.200s from %.200s\n";
2338 #endif
2339  const char *format3 = " 0x%016lx in %.200s from %.200s\n";
2340  const char *format4 = " 0x%016lx in <unknown function>\n";
2341 #else
2342  const char *format1 = " 0x%08lx in %.200s %s 0x%lx from %.200s\n";
2343 #ifdef R__MACOSX
2344  const char *format2 = " 0x%08lx in %.200s\n";
2345 #else
2346  const char *format2 = " 0x%08lx in %.200s at %.200s from %.200s\n";
2347 #endif
2348  const char *format3 = " 0x%08lx in %.200s from %.200s\n";
2349  const char *format4 = " 0x%08lx in <unknown function>\n";
2350 #endif
2351 
2352  char *filter = Which(Getenv("PATH"), cppfilt, kExecutePermission);
2353  if (!filter)
2354  demangle = kFALSE;
2355 
2356 #if (__GNUC__ >= 3)
2357  // try finding supported format option for g++ v3
2358  if (filter) {
2359  FILE *p = OpenPipe(TString::Format("%s --help 2>&1", filter), "r");
2360  TString help;
2361  while (help.Gets(p)) {
2362  if (help.Index("gnu-v3") != kNPOS) {
2363  cppfiltarg = "--format=gnu-v3";
2364  break;
2365  } else if (help.Index("gnu-new-abi") != kNPOS) {
2366  cppfiltarg = "--format=gnu-new-abi";
2367  break;
2368  }
2369  }
2370  ClosePipe(p);
2371  }
2372 #endif
2373  // gdb-backtrace.sh uses gdb to produce a backtrace. See if it is available.
2374  // If it is, use it. If not proceed as before.
2375 #if (defined(R__LINUX) && !defined(R__WINGCC))
2376  // Declare the process that will be generating the stacktrace
2377  // For more see: http://askubuntu.com/questions/41629/after-upgrade-gdb-wont-attach-to-process
2378 #ifdef PR_SET_PTRACER
2379  prctl(PR_SET_PTRACER, getpid(), 0, 0, 0);
2380 #endif
2381 #endif
2382  char *gdb = Which(Getenv("PATH"), "gdb", kExecutePermission);
2383  if (gdb) {
2384  // write custom message file
2385  TString gdbmessf = "gdb-message";
2386  if (gdbmess != "") {
2387  FILE *f = TempFileName(gdbmessf);
2388  fprintf(f, "%s\n", gdbmess.Data());
2389  fclose(f);
2390  }
2391 
2392  // use gdb to get stack trace
2393 #ifdef R__MACOSX
2394  gdbscript += GetExePath();
2395  gdbscript += " ";
2396 #endif
2397  gdbscript += GetPid();
2398  if (gdbmess != "") {
2399  gdbscript += " ";
2400  gdbscript += gdbmessf;
2401  }
2402  gdbscript += " 1>&2";
2403  Exec(gdbscript);
2404  delete [] gdb;
2405  } else {
2406  // addr2line uses debug info to convert addresses into file names
2407  // and line numbers
2408 #ifdef R__MACOSX
2409  char *addr2line = Which(Getenv("PATH"), "atos", kExecutePermission);
2410 #else
2411  char *addr2line = Which(Getenv("PATH"), "addr2line", kExecutePermission);
2412 #endif
2413  if (addr2line) {
2414  // might take some time so tell what we are doing...
2415  if (write(fd, message, strlen(message)) < 0)
2416  Warning("StackTrace", "problems writing line numbers (errno: %d)", TSystem::GetErrno());
2417  }
2418 
2419  // open tmp file for demangled stack trace
2420  TString tmpf1 = "gdb-backtrace";
2421  std::ofstream file1;
2422  if (demangle) {
2423  FILE *f = TempFileName(tmpf1);
2424  if (f) fclose(f);
2425  file1.open(tmpf1);
2426  if (!file1) {
2427  Error("StackTrace", "could not open file %s", tmpf1.Data());
2428  Unlink(tmpf1);
2429  demangle = kFALSE;
2430  }
2431  }
2432 
2433 #ifdef R__MACOSX
2434  if (addr2line)
2435  demangle = kFALSE; // atos always demangles
2436 #endif
2437 
2438  char buffer[4096];
2439  void *trace[kMAX_BACKTRACE_DEPTH];
2440  int depth = backtrace(trace, kMAX_BACKTRACE_DEPTH);
2441  for (int n = 5; n < depth; n++) {
2442  ULong_t addr = (ULong_t) trace[n];
2443  Dl_info info;
2444 
2445  if (dladdr(trace[n], &info) && info.dli_fname && info.dli_fname[0]) {
2446  const char *libname = info.dli_fname;
2447  const char *symname = (info.dli_sname && info.dli_sname[0]) ?
2448  info.dli_sname : "<unknown>";
2449  ULong_t libaddr = (ULong_t) info.dli_fbase;
2450  ULong_t symaddr = (ULong_t) info.dli_saddr;
2451  Bool_t gte = (addr >= symaddr);
2452  ULong_t diff = (gte) ? addr - symaddr : symaddr - addr;
2453  if (addr2line && symaddr) {
2454  Bool_t nodebug = kTRUE;
2455 #ifdef R__MACOSX
2456  if (libaddr) { } // use libaddr
2457 #if defined(MAC_OS_X_VERSION_10_10)
2458  snprintf(buffer, sizeof(buffer), "%s -p %d 0x%016lx", addr2line, GetPid(), addr);
2459 #elif defined(MAC_OS_X_VERSION_10_9)
2460  // suppress deprecation warning with opti
2461  snprintf(buffer, sizeof(buffer), "%s -d -p %d 0x%016lx", addr2line, GetPid(), addr);
2462 #else
2463  snprintf(buffer, sizeof(buffer), "%s -p %d 0x%016lx", addr2line, GetPid(), addr);
2464 #endif
2465 #else
2466  ULong_t offset = (addr >= libaddr) ? addr - libaddr :
2467  libaddr - addr;
2468  TString name = TString(libname);
2469  Bool_t noPath = kFALSE;
2470  Bool_t noShare = kTRUE;
2471  if (name[0] != '/') noPath = kTRUE;
2472  if (name.Contains(".so") || name.Contains(".sl")) noShare = kFALSE;
2473  if (noShare) offset = addr;
2474  if (noPath) name = "`which " + name + "`";
2475  snprintf(buffer, sizeof(buffer), "%s -e %s 0x%016lx", addr2line, name.Data(), offset);
2476 #endif
2477  if (FILE *pf = ::popen(buffer, "r")) {
2478  char buf[2048];
2479  if (fgets(buf, 2048, pf)) {
2480  buf[strlen(buf)-1] = 0; // remove trailing \n
2481  if (strncmp(buf, "??", 2)) {
2482 #ifdef R__MACOSX
2483  snprintf(buffer, sizeof(buffer), format2, addr, buf);
2484 #else
2485  snprintf(buffer, sizeof(buffer), format2, addr, symname, buf, libname);
2486 #endif
2487  nodebug = kFALSE;
2488  }
2489  }
2490  ::pclose(pf);
2491  }
2492  if (nodebug)
2493  snprintf(buffer, sizeof(buffer), format1, addr, symname,
2494  gte ? "+" : "-", diff, libname);
2495  } else {
2496  if (symaddr)
2497  snprintf(buffer, sizeof(buffer), format1, addr, symname,
2498  gte ? "+" : "-", diff, libname);
2499  else
2500  snprintf(buffer, sizeof(buffer), format3, addr, symname, libname);
2501  }
2502  } else {
2503  snprintf(buffer, sizeof(buffer), format4, addr);
2504  }
2505 
2506  if (demangle)
2507  file1 << buffer;
2508  else
2509  if (write(fd, buffer, ::strlen(buffer)) < 0)
2510  Warning("StackTrace", "problems writing buffer (errno: %d)", TSystem::GetErrno());
2511  }
2512 
2513  if (demangle) {
2514  TString tmpf2 = "gdb-backtrace";
2515  FILE *f = TempFileName(tmpf2);
2516  if (f) fclose(f);
2517  file1.close();
2518  snprintf(buffer, sizeof(buffer), "%s %s < %s > %s", filter, cppfiltarg, tmpf1.Data(), tmpf2.Data());
2519  Exec(buffer);
2520  std::ifstream file2(tmpf2);
2521  TString line;
2522  while (file2) {
2523  line = "";
2524  line.ReadString(file2);
2525  if (write(fd, line.Data(), line.Length()) < 0)
2526  Warning("StackTrace", "problems writing line (errno: %d)", TSystem::GetErrno());
2527  }
2528  file2.close();
2529  Unlink(tmpf1);
2530  Unlink(tmpf2);
2531  }
2532 
2533  delete [] addr2line;
2534  }
2535  delete [] filter;
2536 #elif defined(HAVE_EXCPT_H) && defined(HAVE_PDSC_H) && \
2537  defined(HAVE_RLD_INTERFACE_H) // tru64
2538  // Tru64 stack walk. Uses the exception handling library and the
2539  // run-time linker's core functions (loader(5)). FIXME: Tru64
2540  // should have _RLD_DLADDR like IRIX below. Verify and update.
2541 
2542  char buffer [128];
2543  sigcontext context;
2544  int rc = 0;
2545 
2546  exc_capture_context (&context);
2547  while (!rc && context.sc_pc) {
2548  // FIXME: Elf32?
2549  pdsc_crd *func, *base, *crd
2550  = exc_remote_lookup_function_entry(0, 0, context.sc_pc, 0, &func, &base);
2551  Elf32_Addr addr = PDSC_CRD_BEGIN_ADDRESS(base, func);
2552  // const char *name = _rld_address_to_name(addr);
2553  const char *name = "<unknown function>";
2554  sprintf(buffer, " 0x%012lx %.200s + 0x%lx\n",
2555  context.sc_pc, name, context.sc_pc - addr);
2556  write(fd, buffer, ::strlen(buffer));
2557  rc = exc_virtual_unwind(0, &context);
2558  }
2559 #endif
2560 #else //R__MACOSX
2561  macosx_backtrace();
2562 #endif //R__MACOSX
2563 }
2564 
2565 //---- System Logging ----------------------------------------------------------
2566 
2567 ////////////////////////////////////////////////////////////////////////////////
2568 /// Open connection to system log daemon. For the use of the options and
2569 /// facility see the Unix openlog man page.
2570 
2571 void TUnixSystem::Openlog(const char *name, Int_t options, ELogFacility facility)
2572 {
2573  int fac = 0;
2574 
2575  switch (facility) {
2576  case kLogLocal0:
2577  fac = LOG_LOCAL0;
2578  break;
2579  case kLogLocal1:
2580  fac = LOG_LOCAL1;
2581  break;
2582  case kLogLocal2:
2583  fac = LOG_LOCAL2;
2584  break;
2585  case kLogLocal3:
2586  fac = LOG_LOCAL3;
2587  break;
2588  case kLogLocal4:
2589  fac = LOG_LOCAL4;
2590  break;
2591  case kLogLocal5:
2592  fac = LOG_LOCAL5;
2593  break;
2594  case kLogLocal6:
2595  fac = LOG_LOCAL6;
2596  break;
2597  case kLogLocal7:
2598  fac = LOG_LOCAL7;
2599  break;
2600  }
2601 
2602  ::openlog(name, options, fac);
2603 }
2604 
2605 ////////////////////////////////////////////////////////////////////////////////
2606 /// Send mess to syslog daemon. Level is the logging level and mess the
2607 /// message that will be written on the log.
2608 
2609 void TUnixSystem::Syslog(ELogLevel level, const char *mess)
2610 {
2611  // ELogLevel matches exactly the Unix values.
2612  ::syslog(level, "%s", mess);
2613 }
2614 
2615 ////////////////////////////////////////////////////////////////////////////////
2616 /// Close connection to system log daemon.
2617 
2619 {
2620  ::closelog();
2621 }
2622 
2623 //---- Standard output redirection ---------------------------------------------
2624 
2625 ////////////////////////////////////////////////////////////////////////////////
2626 /// Redirect standard output (stdout, stderr) to the specified file.
2627 /// If the file argument is 0 the output is set again to stderr, stdout.
2628 /// The second argument specifies whether the output should be added to the
2629 /// file ("a", default) or the file be truncated before ("w").
2630 /// This function saves internally the current state into a static structure.
2631 /// The call can be made reentrant by specifying the opaque structure pointed
2632 /// by 'h', which is filled with the relevant information. The handle 'h'
2633 /// obtained on the first call must then be used in any subsequent call,
2634 /// included ShowOutput, to display the redirected output.
2635 /// Returns 0 on success, -1 in case of error.
2636 
2637 Int_t TUnixSystem::RedirectOutput(const char *file, const char *mode,
2639 {
2640  // Instance to be used if the caller does not passes 'h'
2641  static RedirectHandle_t loch;
2642 
2643  Int_t rc = 0;
2644 
2645  // Which handle to use ?
2646  RedirectHandle_t *xh = (h) ? h : &loch;
2647 
2648  if (file) {
2649  // Save the paths
2650  Bool_t outdone = kFALSE;
2651  if (xh->fStdOutTty.IsNull()) {
2652  const char *tty = ttyname(STDOUT_FILENO);
2653  if (tty) {
2654  xh->fStdOutTty = tty;
2655  } else {
2656  if ((xh->fStdOutDup = dup(STDOUT_FILENO)) < 0) {
2657  SysError("RedirectOutput", "could not 'dup' stdout (errno: %d)", TSystem::GetErrno());
2658  return -1;
2659  }
2660  outdone = kTRUE;
2661  }
2662  }
2663  if (xh->fStdErrTty.IsNull()) {
2664  const char *tty = ttyname(STDERR_FILENO);
2665  if (tty) {
2666  xh->fStdErrTty = tty;
2667  } else {
2668  if ((xh->fStdErrDup = dup(STDERR_FILENO)) < 0) {
2669  SysError("RedirectOutput", "could not 'dup' stderr (errno: %d)", TSystem::GetErrno());
2670  if (outdone && dup2(xh->fStdOutDup, STDOUT_FILENO) < 0) {
2671  Warning("RedirectOutput", "could not restore stdout (back to original redirected"
2672  " file) (errno: %d)", TSystem::GetErrno());
2673  }
2674  return -1;
2675  }
2676  }
2677  }
2678 
2679  // Make sure mode makes sense; default "a"
2680  const char *m = (mode[0] == 'a' || mode[0] == 'w') ? mode : "a";
2681 
2682  // Current file size
2683  xh->fReadOffSet = 0;
2684  if (m[0] == 'a') {
2685  // If the file exists, save the current size
2686  FileStat_t st;
2687  if (!gSystem->GetPathInfo(file, st))
2688  xh->fReadOffSet = (st.fSize > 0) ? st.fSize : xh->fReadOffSet;
2689  }
2690  xh->fFile = file;
2691 
2692  // Redirect stdout & stderr
2693  if (freopen(file, m, stdout) == 0) {
2694  SysError("RedirectOutput", "could not freopen stdout (errno: %d)", TSystem::GetErrno());
2695  return -1;
2696  }
2697  if (freopen(file, m, stderr) == 0) {
2698  SysError("RedirectOutput", "could not freopen stderr (errno: %d)", TSystem::GetErrno());
2699  if (freopen(xh->fStdOutTty.Data(), "a", stdout) == 0)
2700  SysError("RedirectOutput", "could not restore stdout (errno: %d)", TSystem::GetErrno());
2701  return -1;
2702  }
2703  } else {
2704  // Restore stdout & stderr
2705  fflush(stdout);
2706  if (!(xh->fStdOutTty.IsNull())) {
2707  if (freopen(xh->fStdOutTty.Data(), "a", stdout) == 0) {
2708  SysError("RedirectOutput", "could not restore stdout (errno: %d)", TSystem::GetErrno());
2709  rc = -1;
2710  }
2711  xh->fStdOutTty = "";
2712  } else {
2713  if (close(STDOUT_FILENO) != 0) {
2714  SysError("RedirectOutput",
2715  "problems closing STDOUT_FILENO (%d) before 'dup2' (errno: %d)",
2716  STDOUT_FILENO, TSystem::GetErrno());
2717  rc = -1;
2718  }
2719  if (dup2(xh->fStdOutDup, STDOUT_FILENO) < 0) {
2720  SysError("RedirectOutput", "could not restore stdout (back to original redirected"
2721  " file) (errno: %d)", TSystem::GetErrno());
2722  rc = -1;
2723  }
2724  if (close(xh->fStdOutDup) != 0) {
2725  SysError("RedirectOutput",
2726  "problems closing temporary 'out' descriptor %d (errno: %d)",
2727  TSystem::GetErrno(), xh->fStdOutDup);
2728  rc = -1;
2729  }
2730  }
2731  fflush(stderr);
2732  if (!(xh->fStdErrTty.IsNull())) {
2733  if (freopen(xh->fStdErrTty.Data(), "a", stderr) == 0) {
2734  SysError("RedirectOutput", "could not restore stderr (errno: %d)", TSystem::GetErrno());
2735  rc = -1;
2736  }
2737  xh->fStdErrTty = "";
2738  } else {
2739  if (close(STDERR_FILENO) != 0) {
2740  SysError("RedirectOutput",
2741  "problems closing STDERR_FILENO (%d) before 'dup2' (errno: %d)",
2742  STDERR_FILENO, TSystem::GetErrno());
2743  rc = -1;
2744  }
2745  if (dup2(xh->fStdErrDup, STDERR_FILENO) < 0) {
2746  SysError("RedirectOutput", "could not restore stderr (back to original redirected"
2747  " file) (errno: %d)", TSystem::GetErrno());
2748  rc = -1;
2749  }
2750  if (close(xh->fStdErrDup) != 0) {
2751  SysError("RedirectOutput",
2752  "problems closing temporary 'err' descriptor %d (errno: %d)",
2753  TSystem::GetErrno(), xh->fStdErrDup);
2754  rc = -1;
2755  }
2756  }
2757  // Reset the static instance, if using that
2758  if (xh == &loch)
2759  xh->Reset();
2760  }
2761  return rc;
2762 }
2763 
2764 //---- dynamic loading and linking ---------------------------------------------
2765 
2766 ////////////////////////////////////////////////////////////////////////////////
2767 ///dynamic linking of module
2768 
2769 Func_t TUnixSystem::DynFindSymbol(const char * /*module*/, const char *entry)
2770 {
2771  return TSystem::DynFindSymbol("*", entry);
2772 }
2773 
2774 ////////////////////////////////////////////////////////////////////////////////
2775 /// Load a shared library. Returns 0 on successful loading, 1 in
2776 /// case lib was already loaded and -1 in case lib does not exist
2777 /// or in case of error.
2778 
2779 int TUnixSystem::Load(const char *module, const char *entry, Bool_t system)
2780 {
2781  return TSystem::Load(module, entry, system);
2782 }
2783 
2784 ////////////////////////////////////////////////////////////////////////////////
2785 /// Unload a shared library.
2786 
2787 void TUnixSystem::Unload(const char *module)
2788 {
2789  if (module) { TSystem::Unload(module); }
2790 }
2791 
2792 ////////////////////////////////////////////////////////////////////////////////
2793 /// List symbols in a shared library.
2794 
2795 void TUnixSystem::ListSymbols(const char * /*module*/, const char * /*regexp*/)
2796 {
2797  Error("ListSymbols", "not yet implemented");
2798 }
2799 
2800 ////////////////////////////////////////////////////////////////////////////////
2801 /// List all loaded shared libraries.
2802 
2803 void TUnixSystem::ListLibraries(const char *regexp)
2804 {
2805  TSystem::ListLibraries(regexp);
2806 }
2807 
2808 ////////////////////////////////////////////////////////////////////////////////
2809 /// Get list of shared libraries loaded at the start of the executable.
2810 /// Returns 0 in case list cannot be obtained or in case of error.
2811 
2813 {
2814  static TString linkedLibs;
2815  static Bool_t once = kFALSE;
2816 
2818 
2819  if (!linkedLibs.IsNull())
2820  return linkedLibs;
2821 
2822  if (once)
2823  return 0;
2824 
2825 #if !defined(R__MACOSX)
2826  const char *exe = GetExePath();
2827  if (!exe || !*exe)
2828  return 0;
2829 #endif
2830 
2831 #if defined(R__MACOSX)
2832  DylibAdded(0, 0);
2833  linkedLibs = gLinkedDylibs;
2834 #if 0
2835  FILE *p = OpenPipe(TString::Format("otool -L %s", exe), "r");
2836  TString otool;
2837  while (otool.Gets(p)) {
2838  TString delim(" \t");
2839  TObjArray *tok = otool.Tokenize(delim);
2840  TString dylib = ((TObjString*)tok->At(0))->String();
2841  if (dylib.EndsWith(".dylib") && !dylib.Contains("/libSystem.B.dylib")) {
2842  if (!linkedLibs.IsNull())
2843  linkedLibs += " ";
2844  linkedLibs += dylib;
2845  }
2846  delete tok;
2847  }
2848  if (p) {
2849  ClosePipe(p);
2850  }
2851 #endif
2852 #elif defined(R__LINUX) || defined(R__SOLARIS) || defined(R__AIX)
2853 #if defined(R__WINGCC )
2854  const char *cLDD="cygcheck";
2855  const char *cSOEXT=".dll";
2856  size_t lenexe = strlen(exe);
2857  if (strcmp(exe + lenexe - 4, ".exe")
2858  && strcmp(exe + lenexe - 4, ".dll")) {
2859  // it's not a dll and exe doesn't end on ".exe";
2860  // need to add it for cygcheck to find it:
2861  char* longerexe = new char[lenexe + 5];
2862  strlcpy(longerexe, exe,lenexe+5);
2863  strlcat(longerexe, ".exe",lenexe+5);
2864  delete [] exe;
2865  exe = longerexe;
2866  }
2867  TRegexp sovers = "\\.so\\.[0-9]+";
2868 #else
2869  const char *cLDD="ldd";
2870 #if defined(R__AIX)
2871  const char *cSOEXT=".a";
2872  TRegexp sovers = "\\.a\\.[0-9]+";
2873 #else
2874  const char *cSOEXT=".so";
2875  TRegexp sovers = "\\.so\\.[0-9]+";
2876 #endif
2877 #endif
2878  FILE *p = OpenPipe(TString::Format("%s '%s'", cLDD, exe), "r");
2879  if (p) {
2880  TString ldd;
2881  while (ldd.Gets(p)) {
2882  TString delim(" \t");
2883  TObjArray *tok = ldd.Tokenize(delim);
2884 
2885  // expected format:
2886  // libCore.so => /home/rdm/root/lib/libCore.so (0x40017000)
2887  TObjString *solibName = (TObjString*)tok->At(2);
2888  if (!solibName) {
2889  // case where there is only one name of the list:
2890  // /usr/platform/SUNW,UltraAX-i2/lib/libc_psr.so.1
2891  solibName = (TObjString*)tok->At(0);
2892  }
2893  if (solibName) {
2894  TString solib = solibName->String();
2895  Ssiz_t idx = solib.Index(sovers);
2896  if (solib.EndsWith(cSOEXT) || idx != kNPOS) {
2897  if (idx != kNPOS)
2898  solib.Remove(idx+3);
2899  if (!AccessPathName(solib, kReadPermission)) {
2900  if (!linkedLibs.IsNull())
2901  linkedLibs += " ";
2902  linkedLibs += solib;
2903  }
2904  }
2905  }
2906  delete tok;
2907  }
2908  ClosePipe(p);
2909  }
2910 #endif
2911 
2912  once = kTRUE;
2913 
2914  if (linkedLibs.IsNull())
2915  return 0;
2916 
2917  return linkedLibs;
2918 }
2919 
2920 //---- Time & Date -------------------------------------------------------------
2921 
2922 ////////////////////////////////////////////////////////////////////////////////
2923 /// Get current time in milliseconds since 0:00 Jan 1 1995.
2924 
2926 {
2927  return UnixNow();
2928 }
2929 
2930 ////////////////////////////////////////////////////////////////////////////////
2931 /// Handle and dispatch timers. If mode = kTRUE dispatch synchronous
2932 /// timers else a-synchronous timers.
2933 
2935 {
2936  if (!fTimers) return kFALSE;
2937 
2938  fInsideNotify = kTRUE;
2939 
2940  TOrdCollectionIter it((TOrdCollection*)fTimers);
2941  TTimer *t;
2942  Bool_t timedout = kFALSE;
2943 
2944  while ((t = (TTimer *) it.Next())) {
2945  // NB: the timer resolution is added in TTimer::CheckTimer()
2946  Long64_t now = UnixNow();
2947  if (mode && t->IsSync()) {
2948  if (t->CheckTimer(now))
2949  timedout = kTRUE;
2950  } else if (!mode && t->IsAsync()) {
2951  if (t->CheckTimer(now)) {
2952  UnixSetitimer(NextTimeOut(kFALSE));
2953  timedout = kTRUE;
2954  }
2955  }
2956  }
2957  fInsideNotify = kFALSE;
2958  return timedout;
2959 }
2960 
2961 ////////////////////////////////////////////////////////////////////////////////
2962 /// Add timer to list of system timers.
2963 
2965 {
2966  TSystem::AddTimer(ti);
2967  ResetTimer(ti);
2968 }
2969 
2970 ////////////////////////////////////////////////////////////////////////////////
2971 /// Remove timer from list of system timers.
2972 
2974 {
2975  if (!ti) return 0;
2976 
2978 
2979  TTimer *t = TSystem::RemoveTimer(ti);
2980  if (ti->IsAsync())
2981  UnixSetitimer(NextTimeOut(kFALSE));
2982  return t;
2983 }
2984 
2985 ////////////////////////////////////////////////////////////////////////////////
2986 /// Reset a-sync timer.
2987 
2989 {
2990  if (!fInsideNotify && ti && ti->IsAsync())
2991  UnixSetitimer(NextTimeOut(kFALSE));
2992 }
2993 
2994 //---- RPC ---------------------------------------------------------------------
2995 
2996 ////////////////////////////////////////////////////////////////////////////////
2997 /// Get Internet Protocol (IP) address of host. Returns an TInetAddress
2998 /// object. To see if the hostname lookup was successfull call
2999 /// TInetAddress::IsValid().
3000 
3002 {
3003  UInt_t addr; // good for 4 byte addresses
3004  Bool_t isinaddr = kFALSE;
3005 #ifdef HASNOT_INETATON
3006  isinaddr = (addr = (UInt_t)inet_addr(hostname)) != INADDR_NONE) ? kTRUE : kFALSE;
3007 #else
3008  struct in_addr ad;
3009  isinaddr = inet_aton(hostname, &ad);
3010  if (isinaddr) memcpy(&addr, &ad.s_addr, sizeof(ad.s_addr));
3011 #endif
3012 
3013  std::string host(hostname);
3014  if (isinaddr) {
3015  struct sockaddr_in sin;
3016  sin.sin_family = AF_INET;
3017  sin.sin_port = 0;
3018  memcpy(&sin.sin_addr.s_addr, &addr, sizeof(sin.sin_addr.s_addr));
3019  memset(&sin.sin_zero[0], 0, sizeof(sin.sin_zero));
3020  struct sockaddr *sa = (struct sockaddr *) &sin; /* input */
3021 
3022  char hbuf[NI_MAXHOST];
3023 
3024  int rc = getnameinfo(sa, sizeof(struct sockaddr), hbuf, sizeof(hbuf), nullptr, 0, NI_NAMEREQD);
3025  if (rc != 0 ) {
3026  if (rc == EAI_NONAME) {
3027  if (gDebug > 0)
3028  Error("GetHostByName", "unknown host '%s'", hostname);
3029  return TInetAddress("UnNamedHost", 0, -1);
3030  } else {
3031  Error("GetHostByName", "getnameinfo failed for '%s': '%s'", hostname, gai_strerror(rc));
3032  return TInetAddress();
3033  }
3034  }
3035  host = hbuf;
3036  }
3037 
3038  // Hints structure
3039  struct addrinfo hints;
3040  memset(&hints, 0, sizeof(struct addrinfo));
3041  hints.ai_family = AF_INET; // Ask IPv4
3042  hints.ai_socktype = 0; // Any socket type
3043  hints.ai_flags = AI_CANONNAME; // Get canonical name
3044  hints.ai_protocol = 0; // Any protocol
3045  hints.ai_canonname = nullptr;
3046  hints.ai_addr = nullptr;
3047  hints.ai_next = nullptr;
3048 
3049  struct addrinfo *res;
3050  int rc = getaddrinfo(host.c_str(), nullptr, &hints, &res);
3051  if (rc != 0) {
3052  if (rc == EAI_NONAME) {
3053  if (gDebug > 0)
3054  Error("GetHostByName", "unknown host '%s'", host.c_str());
3055  return TInetAddress("UnNamedHost", 0, -1);
3056  } else {
3057  Error("GetHostByName", "getaddrinfo failed for '%s': '%s'", host.c_str(), gai_strerror(rc));
3058  return TInetAddress();
3059  }
3060  }
3061  if (res[0].ai_canonname) host = res[0].ai_canonname;
3062  // Prepare output
3063  TInetAddress a(host.c_str(),
3064  ntohl(((sockaddr_in *)(res[0].ai_addr))->sin_addr.s_addr),
3065  res[0].ai_family);
3066  struct addrinfo *rp = res[0].ai_next;
3067  for (; rp != NULL; rp = rp->ai_next) {
3068  UInt_t arp = ntohl(((sockaddr_in *)(rp->ai_addr))->sin_addr.s_addr);
3069  std::vector<UInt_t> addrs = a.GetAddresses();
3070  Bool_t newad = kTRUE;
3071  for (UInt_t sad : addrs) {
3072  if (sad == arp) {
3073  newad = kFALSE;
3074  break;
3075  }
3076  }
3077  if (newad) {
3078  a.AddAddress(ntohl(((sockaddr_in *)(rp->ai_addr))->sin_addr.s_addr));
3079  if (rp->ai_canonname) a.AddAlias(rp->ai_canonname);
3080  }
3081  }
3082  // Release memory
3083  freeaddrinfo(res);
3084  // Done
3085  return a;
3086 }
3087 
3088 ////////////////////////////////////////////////////////////////////////////////
3089 /// Get Internet Protocol (IP) address of host and port #.
3090 
3092 {
3093  struct sockaddr_in addr;
3094 #if defined(USE_SIZE_T)
3095  size_t len = sizeof(addr);
3096 #elif defined(USE_SOCKLEN_T)
3097  socklen_t len = sizeof(addr);
3098 #else
3099  int len = sizeof(addr);
3100 #endif
3101 
3102  if (getsockname(sock, (struct sockaddr *)&addr, &len) == -1) {
3103  SysError("GetSockName", "getsockname");
3104  return TInetAddress();
3105  }
3106 
3107  struct sockaddr *sa = (struct sockaddr *) &addr; /* input */
3108  char hbuf[NI_MAXHOST];
3109  int rc = 0;
3110  if ((rc = getnameinfo(sa, sizeof(struct sockaddr), hbuf, sizeof(hbuf),
3111  nullptr, 0, 0)) == 0) {
3112  TInetAddress a = GetHostByName(hbuf);
3113  if (a.IsValid()) {
3114  a.fFamily = addr.sin_family;
3115  a.fPort = ntohs(addr.sin_port);
3116  return a;
3117  }
3118  }
3119  // Failure: return minimal information
3120  UInt_t iaddr;
3121  memcpy(&iaddr, &addr.sin_addr, sizeof(addr.sin_addr));
3122  return TInetAddress("????", ntohl(iaddr), AF_INET, ntohs(addr.sin_port));
3123 }
3124 
3125 ////////////////////////////////////////////////////////////////////////////////
3126 /// Get Internet Protocol (IP) address of remote host and port #.
3127 
3129 {
3130  struct sockaddr_in addr;
3131 #if defined(USE_SIZE_T)
3132  size_t len = sizeof(addr);
3133 #elif defined(USE_SOCKLEN_T)
3134  socklen_t len = sizeof(addr);
3135 #else
3136  int len = sizeof(addr);
3137 #endif
3138 
3139  if (getpeername(sock, (struct sockaddr *)&addr, &len) == -1) {
3140  SysError("GetPeerName", "getpeername");
3141  return TInetAddress();
3142  }
3143 
3144  int rc = 0;
3145  struct sockaddr *sa = (struct sockaddr *) &addr; /* input */
3146  char hbuf[NI_MAXHOST];
3147  if ((rc = getnameinfo(sa, sizeof(struct sockaddr), hbuf, sizeof(hbuf),
3148  nullptr, 0, 0)) == 0) {
3149  TInetAddress a = GetHostByName(hbuf);
3150  if (a.IsValid()) {
3151  a.fFamily = addr.sin_family;
3152  a.fPort = ntohs(addr.sin_port);
3153  return a;
3154  }
3155  }
3156  // Failure: return minimal information
3157  UInt_t iaddr;
3158  memcpy(&iaddr, &addr.sin_addr, sizeof(addr.sin_addr));
3159  return TInetAddress("????", ntohl(iaddr), AF_INET, ntohs(addr.sin_port));
3160 }
3161 
3162 ////////////////////////////////////////////////////////////////////////////////
3163 /// Get port # of internet service.
3164 
3165 int TUnixSystem::GetServiceByName(const char *servicename)
3166 {
3167  struct servent *sp;
3168 
3169  if ((sp = getservbyname(servicename, kProtocolName)) == 0) {
3170  Error("GetServiceByName", "no service \"%s\" with protocol \"%s\"\n",
3171  servicename, kProtocolName);
3172  return -1;
3173  }
3174  return ntohs(sp->s_port);
3175 }
3176 
3177 ////////////////////////////////////////////////////////////////////////////////
3178 /// Get name of internet service.
3179 
3181 {
3182  struct servent *sp;
3183 
3184  if ((sp = getservbyport(htons(port), kProtocolName)) == 0) {
3185  //::Error("GetServiceByPort", "no service \"%d\" with protocol \"%s\"",
3186  // port, kProtocolName);
3187  return Form("%d", port);
3188  }
3189  return sp->s_name;
3190 }
3191 
3192 ////////////////////////////////////////////////////////////////////////////////
3193 /// Connect to service servicename on server servername.
3194 
3195 int TUnixSystem::ConnectService(const char *servername, int port,
3196  int tcpwindowsize, const char *protocol)
3197 {
3198  if (!strcmp(servername, "unix")) {
3199  return UnixUnixConnect(port);
3200  } else if (!gSystem->AccessPathName(servername) || servername[0] == '/') {
3201  return UnixUnixConnect(servername);
3202  }
3203 
3204  if (!strcmp(protocol, "udp")){
3205  return UnixUdpConnect(servername, port);
3206  }
3207 
3208  return UnixTcpConnect(servername, port, tcpwindowsize);
3209 }
3210 
3211 ////////////////////////////////////////////////////////////////////////////////
3212 /// Open a connection to a service on a server. Returns -1 in case
3213 /// connection cannot be opened.
3214 /// Use tcpwindowsize to specify the size of the receive buffer, it has
3215 /// to be specified here to make sure the window scale option is set (for
3216 /// tcpwindowsize > 65KB and for platforms supporting window scaling).
3217 /// Is called via the TSocket constructor.
3218 
3219 int TUnixSystem::OpenConnection(const char *server, int port, int tcpwindowsize, const char *protocol)
3220 {
3221  return ConnectService(server, port, tcpwindowsize, protocol);
3222 }
3223 
3224 ////////////////////////////////////////////////////////////////////////////////
3225 /// Announce TCP/IP service.
3226 /// Open a socket, bind to it and start listening for TCP/IP connections
3227 /// on the port. If reuse is true reuse the address, backlog specifies
3228 /// how many sockets can be waiting to be accepted.
3229 /// Use tcpwindowsize to specify the size of the receive buffer, it has
3230 /// to be specified here to make sure the window scale option is set (for
3231 /// tcpwindowsize > 65KB and for platforms supporting window scaling).
3232 /// Returns socket fd or -1 if socket() failed, -2 if bind() failed
3233 /// or -3 if listen() failed.
3234 
3235 int TUnixSystem::AnnounceTcpService(int port, Bool_t reuse, int backlog,
3236  int tcpwindowsize)
3237 {
3238  return UnixTcpService(port, reuse, backlog, tcpwindowsize);
3239 }
3240 
3241 ////////////////////////////////////////////////////////////////////////////////
3242 /// Announce UDP service.
3243 
3244 int TUnixSystem::AnnounceUdpService(int port, int backlog)
3245 {
3246  return UnixUdpService(port, backlog);
3247 }
3248 
3249 ////////////////////////////////////////////////////////////////////////////////
3250 /// Announce unix domain service on path "kServerPath/<port>"
3251 
3252 int TUnixSystem::AnnounceUnixService(int port, int backlog)
3253 {
3254  return UnixUnixService(port, backlog);
3255 }
3256 
3257 ////////////////////////////////////////////////////////////////////////////////
3258 /// Announce unix domain service on path 'sockpath'
3259 
3260 int TUnixSystem::AnnounceUnixService(const char *sockpath, int backlog)
3261 {
3262  return UnixUnixService(sockpath, backlog);
3263 }
3264 
3265 ////////////////////////////////////////////////////////////////////////////////
3266 /// Accept a connection. In case of an error return -1. In case
3267 /// non-blocking I/O is enabled and no connections are available
3268 /// return -2.
3269 
3271 {
3272  int soc = -1;
3273 
3274  while ((soc = ::accept(sock, 0, 0)) == -1 && GetErrno() == EINTR)
3275  ResetErrno();
3276 
3277  if (soc == -1) {
3278  if (GetErrno() == EWOULDBLOCK)
3279  return -2;
3280  else {
3281  SysError("AcceptConnection", "accept");
3282  return -1;
3283  }
3284  }
3285 
3286  return soc;
3287 }
3288 
3289 ////////////////////////////////////////////////////////////////////////////////
3290 /// Close socket.
3291 
3293 {
3294  if (sock < 0) return;
3295 
3296 #if !defined(R__AIX) || defined(_AIX41) || defined(_AIX43)
3297  if (force)
3298  ::shutdown(sock, 2); // will also close connection of parent
3299 #endif
3300 
3301  while (::close(sock) == -1 && GetErrno() == EINTR)
3302  ResetErrno();
3303 }
3304 
3305 ////////////////////////////////////////////////////////////////////////////////
3306 /// Receive a buffer headed by a length indicator. Length is the size of
3307 /// the buffer. Returns the number of bytes received in buf or -1 in
3308 /// case of error.
3309 
3310 int TUnixSystem::RecvBuf(int sock, void *buf, int length)
3311 {
3312  Int_t header;
3313 
3314  if (UnixRecv(sock, &header, sizeof(header), 0) > 0) {
3315  int count = ntohl(header);
3316 
3317  if (count > length) {
3318  Error("RecvBuf", "record header exceeds buffer size");
3319  return -1;
3320  } else if (count > 0) {
3321  if (UnixRecv(sock, buf, count, 0) < 0) {
3322  Error("RecvBuf", "cannot receive buffer");
3323  return -1;
3324  }
3325  }
3326  return count;
3327  }
3328  return -1;
3329 }
3330 
3331 ////////////////////////////////////////////////////////////////////////////////
3332 /// Send a buffer headed by a length indicator. Returns length of sent buffer
3333 /// or -1 in case of error.
3334 
3335 int TUnixSystem::SendBuf(int sock, const void *buf, int length)
3336 {
3337  Int_t header = htonl(length);
3338 
3339  if (UnixSend(sock, &header, sizeof(header), 0) < 0) {
3340  Error("SendBuf", "cannot send header");
3341  return -1;
3342  }
3343  if (length > 0) {
3344  if (UnixSend(sock, buf, length, 0) < 0) {
3345  Error("SendBuf", "cannot send buffer");
3346  return -1;
3347  }
3348  }
3349  return length;
3350 }
3351 
3352 ////////////////////////////////////////////////////////////////////////////////
3353 /// Receive exactly length bytes into buffer. Use opt to receive out-of-band
3354 /// data or to have a peek at what is in the buffer (see TSocket). Buffer
3355 /// must be able to store at least length bytes. Returns the number of
3356 /// bytes received (can be 0 if other side of connection was closed) or -1
3357 /// in case of error, -2 in case of MSG_OOB and errno == EWOULDBLOCK, -3
3358 /// in case of MSG_OOB and errno == EINVAL and -4 in case of kNoBlock and
3359 /// errno == EWOULDBLOCK. Returns -5 if pipe broken or reset by peer
3360 /// (EPIPE || ECONNRESET).
3361 
3362 int TUnixSystem::RecvRaw(int sock, void *buf, int length, int opt)
3363 {
3364  int flag;
3365 
3366  switch (opt) {
3367  case kDefault:
3368  flag = 0;
3369  break;
3370  case kOob:
3371  flag = MSG_OOB;
3372  break;
3373  case kPeek:
3374  flag = MSG_PEEK;
3375  break;
3376  case kDontBlock:
3377  flag = -1;
3378  break;
3379  default:
3380  flag = 0;
3381  break;
3382  }
3383 
3384  int n;
3385  if ((n = UnixRecv(sock, buf, length, flag)) <= 0) {
3386  if (n == -1 && GetErrno() != EINTR)
3387  Error("RecvRaw", "cannot receive buffer");
3388  return n;
3389  }
3390  return n;
3391 }
3392 
3393 ////////////////////////////////////////////////////////////////////////////////
3394 /// Send exactly length bytes from buffer. Use opt to send out-of-band
3395 /// data (see TSocket). Returns the number of bytes sent or -1 in case of
3396 /// error. Returns -4 in case of kNoBlock and errno == EWOULDBLOCK.
3397 /// Returns -5 if pipe broken or reset by peer (EPIPE || ECONNRESET).
3398 
3399 int TUnixSystem::SendRaw(int sock, const void *buf, int length, int opt)
3400 {
3401  int flag;
3402 
3403  switch (opt) {
3404  case kDefault:
3405  flag = 0;
3406  break;
3407  case kOob:
3408  flag = MSG_OOB;
3409  break;
3410  case kDontBlock:
3411  flag = -1;
3412  break;
3413  case kPeek: // receive only option (see RecvRaw)
3414  default:
3415  flag = 0;
3416  break;
3417  }
3418 
3419  int n;
3420  if ((n = UnixSend(sock, buf, length, flag)) <= 0) {
3421  if (n == -1 && GetErrno() != EINTR)
3422  Error("SendRaw", "cannot send buffer");
3423  return n;
3424  }
3425  return n;
3426 }
3427 
3428 ////////////////////////////////////////////////////////////////////////////////
3429 /// Set socket option.
3430 
3431 int TUnixSystem::SetSockOpt(int sock, int opt, int val)
3432 {
3433  if (sock < 0) return -1;
3434 
3435  switch (opt) {
3436  case kSendBuffer:
3437  if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, sizeof(val)) == -1) {
3438  SysError("SetSockOpt", "setsockopt(SO_SNDBUF)");
3439  return -1;
3440  }
3441  break;
3442  case kRecvBuffer:
3443  if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, sizeof(val)) == -1) {
3444  SysError("SetSockOpt", "setsockopt(SO_RCVBUF)");
3445  return -1;
3446  }
3447  break;
3448  case kOobInline:
3449  if (setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char*)&val, sizeof(val)) == -1) {
3450  SysError("SetSockOpt", "setsockopt(SO_OOBINLINE)");
3451  return -1;
3452  }
3453  break;
3454  case kKeepAlive:
3455  if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(val)) == -1) {
3456  SysError("SetSockOpt", "setsockopt(SO_KEEPALIVE)");
3457  return -1;
3458  }
3459  break;
3460  case kReuseAddr:
3461  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val)) == -1) {
3462  SysError("SetSockOpt", "setsockopt(SO_REUSEADDR)");
3463  return -1;
3464  }
3465  break;
3466  case kNoDelay:
3467  if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(val)) == -1) {
3468  SysError("SetSockOpt", "setsockopt(TCP_NODELAY)");
3469  return -1;
3470  }
3471  break;
3472  case kNoBlock:
3473  if (ioctl(sock, FIONBIO, (char*)&val) == -1) {
3474  SysError("SetSockOpt", "ioctl(FIONBIO)");
3475  return -1;
3476  }
3477  break;
3478  case kProcessGroup:
3479 #ifndef R__WINGCC
3480  if (ioctl(sock, SIOCSPGRP, (char*)&val) == -1) {
3481  SysError("SetSockOpt", "ioctl(SIOCSPGRP)");
3482  return -1;
3483  }
3484 #else
3485  Error("SetSockOpt", "ioctl(SIOCGPGRP) not supported on cygwin/gcc");
3486  return -1;
3487 #endif
3488  break;
3489  case kAtMark: // read-only option (see GetSockOpt)
3490  case kBytesToRead: // read-only option
3491  default:
3492  Error("SetSockOpt", "illegal option (%d)", opt);
3493  return -1;
3494  }
3495  return 0;
3496 }
3497 
3498 ////////////////////////////////////////////////////////////////////////////////
3499 /// Get socket option.
3500 
3501 int TUnixSystem::GetSockOpt(int sock, int opt, int *val)
3502 {
3503  if (sock < 0) return -1;
3504 
3505 #if defined(USE_SOCKLEN_T) || defined(_AIX43)
3506  socklen_t optlen = sizeof(*val);
3507 #elif defined(USE_SIZE_T)
3508  size_t optlen = sizeof(*val);
3509 #else
3510  int optlen = sizeof(*val);
3511 #endif
3512 
3513  switch (opt) {
3514  case kSendBuffer:
3515  if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)val, &optlen) == -1) {
3516  SysError("GetSockOpt", "getsockopt(SO_SNDBUF)");
3517  return -1;
3518  }
3519  break;
3520  case kRecvBuffer:
3521  if (getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)val, &optlen) == -1) {
3522  SysError("GetSockOpt", "getsockopt(SO_RCVBUF)");
3523  return -1;
3524  }
3525  break;
3526  case kOobInline:
3527  if (getsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char*)val, &optlen) == -1) {
3528  SysError("GetSockOpt", "getsockopt(SO_OOBINLINE)");
3529  return -1;
3530  }
3531  break;
3532  case kKeepAlive:
3533  if (getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)val, &optlen) == -1) {
3534  SysError("GetSockOpt", "getsockopt(SO_KEEPALIVE)");
3535  return -1;
3536  }
3537  break;
3538  case kReuseAddr:
3539  if (getsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)val, &optlen) == -1) {
3540  SysError("GetSockOpt", "getsockopt(SO_REUSEADDR)");
3541  return -1;
3542  }
3543  break;
3544  case kNoDelay:
3545  if (getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)val, &optlen) == -1) {
3546  SysError("GetSockOpt", "getsockopt(TCP_NODELAY)");
3547  return -1;
3548  }
3549  break;
3550  case kNoBlock:
3551  int flg;
3552  if ((flg = fcntl(sock, F_GETFL, 0)) == -1) {
3553  SysError("GetSockOpt", "fcntl(F_GETFL)");
3554  return -1;
3555  }
3556  *val = flg & O_NDELAY;
3557  break;
3558  case kProcessGroup:
3559 #if !defined(R__LYNXOS) && !defined(R__WINGCC)
3560  if (ioctl(sock, SIOCGPGRP, (char*)val) == -1) {
3561  SysError("GetSockOpt", "ioctl(SIOCGPGRP)");
3562  return -1;
3563  }
3564 #else
3565  Error("GetSockOpt", "ioctl(SIOCGPGRP) not supported on LynxOS and cygwin/gcc");
3566  return -1;
3567 #endif
3568  break;
3569  case kAtMark:
3570 #if !defined(R__LYNXOS)
3571  if (ioctl(sock, SIOCATMARK, (char*)val) == -1) {
3572  SysError("GetSockOpt", "ioctl(SIOCATMARK)");
3573  return -1;
3574  }
3575 #else
3576  Error("GetSockOpt", "ioctl(SIOCATMARK) not supported on LynxOS");
3577  return -1;
3578 #endif
3579  break;
3580  case kBytesToRead:
3581 #if !defined(R__LYNXOS)
3582  if (ioctl(sock, FIONREAD, (char*)val) == -1) {
3583  SysError("GetSockOpt", "ioctl(FIONREAD)");
3584  return -1;
3585  }
3586 #else
3587  Error("GetSockOpt", "ioctl(FIONREAD) not supported on LynxOS");
3588  return -1;
3589 #endif
3590  break;
3591  default:
3592  Error("GetSockOpt", "illegal option (%d)", opt);
3593  *val = 0;
3594  return -1;
3595  }
3596  return 0;
3597 }
3598 
3599 //////////////////////////////////////////////////////////////////////////
3600 // //
3601 // Static Protected Unix Interface functions. //
3602 // //
3603 //////////////////////////////////////////////////////////////////////////
3604 
3605 //---- signals -----------------------------------------------------------------
3606 
3607 static struct Signalmap_t {
3608  int fCode;
3609  SigHandler_t fHandler;
3610  struct sigaction *fOldHandler;
3611  const char *fSigName;
3612 } gSignalMap[kMAXSIGNALS] = { // the order of the signals should be identical
3613  { SIGBUS, 0, 0, "bus error" }, // to the one in TSysEvtHandler.h
3614  { SIGSEGV, 0, 0, "segmentation violation" },
3615  { SIGSYS, 0, 0, "bad argument to system call" },
3616  { SIGPIPE, 0, 0, "write on a pipe with no one to read it" },
3617  { SIGILL, 0, 0, "illegal instruction" },
3618  { SIGQUIT, 0, 0, "quit" },
3619  { SIGINT, 0, 0, "interrupt" },
3620  { SIGWINCH, 0, 0, "window size change" },
3621  { SIGALRM, 0, 0, "alarm clock" },
3622  { SIGCHLD, 0, 0, "death of a child" },
3623  { SIGURG, 0, 0, "urgent data arrived on an I/O channel" },
3624  { SIGFPE, 0, 0, "floating point exception" },
3625  { SIGTERM, 0, 0, "termination signal" },
3626  { SIGUSR1, 0, 0, "user-defined signal 1" },
3627  { SIGUSR2, 0, 0, "user-defined signal 2" }
3628 };
3629 
3630 
3631 ////////////////////////////////////////////////////////////////////////////////
3632 /// Call the signal handler associated with the signal.
3633 
3634 static void sighandler(int sig)
3635 {
3636  for (int i= 0; i < kMAXSIGNALS; i++) {
3637  if (gSignalMap[i].fCode == sig) {
3638  (*gSignalMap[i].fHandler)((ESignals)i);
3639  return;
3640  }
3641  }
3642 }
3643 
3644 ////////////////////////////////////////////////////////////////////////////////
3645 /// Handle and dispatch signals.
3646 
3648 {
3649  switch (sig) {
3650  case kSigAlarm:
3651  DispatchTimers(kFALSE);
3652  break;
3653  case kSigChild:
3654  CheckChilds();
3655  break;
3656  case kSigBus:
3659  case kSigFloatingException:
3660  Break("TUnixSystem::DispatchSignals", "%s", UnixSigname(sig));
3661  StackTrace();
3662  if (gApplication)
3663  //sig is ESignal, should it be mapped to the correct signal number?
3665  else
3666  //map to the real signal code + set the
3667  //high order bit to indicate a signal (?)
3668  Exit(gSignalMap[sig].fCode + 0x80);
3669  break;
3670  case kSigSystem:
3671  case kSigPipe:
3672  Break("TUnixSystem::DispatchSignals", "%s", UnixSigname(sig));
3673  break;
3674  case kSigWindowChanged:
3675  Gl_windowchanged();
3676  break;
3677  default:
3678  fSignals->Set(sig);
3679  fSigcnt++;
3680  break;
3681  }
3682 
3683  // check a-synchronous signals
3684  if (fSigcnt > 0 && fSignalHandler->GetSize() > 0)
3685  CheckSignals(kFALSE);
3686 }
3687 
3688 ////////////////////////////////////////////////////////////////////////////////
3689 /// Set a signal handler for a signal.
3690 
3692 {
3693  if (gEnv && !gEnv->GetValue("Root.ErrorHandlers", 1))
3694  return;
3695 
3696  if (gSignalMap[sig].fHandler != handler) {
3697  struct sigaction sigact;
3698 
3699  gSignalMap[sig].fHandler = handler;
3700  gSignalMap[sig].fOldHandler = new struct sigaction();
3701 
3702 #if defined(R__SUN)
3703  sigact.sa_handler = (void (*)())sighandler;
3704 #elif defined(R__SOLARIS)
3705  sigact.sa_handler = sighandler;
3706 #elif defined(R__LYNXOS)
3707 # if (__GNUG__>=3)
3708  sigact.sa_handler = sighandler;
3709 # else
3710  sigact.sa_handler = (void (*)(...))sighandler;
3711 # endif
3712 #else
3713  sigact.sa_handler = sighandler;
3714 #endif
3715  sigemptyset(&sigact.sa_mask);
3716  sigact.sa_flags = 0;
3717 #if defined(SA_RESTART)
3718  sigact.sa_flags |= SA_RESTART;
3719 #endif
3720  if (sigaction(gSignalMap[sig].fCode, &sigact,
3721  gSignalMap[sig].fOldHandler) < 0)
3722  ::SysError("TUnixSystem::UnixSignal", "sigaction");
3723  }
3724 }
3725 
3726 ////////////////////////////////////////////////////////////////////////////////
3727 /// If ignore is true ignore the specified signal, else restore previous
3728 /// behaviour.
3729 
3731 {
3732  TTHREAD_TLS(Bool_t) ignoreSig[kMAXSIGNALS] = { kFALSE };
3733  TTHREAD_TLS_ARRAY(struct sigaction,kMAXSIGNALS,oldsigact);
3734 
3735  if (ignore != ignoreSig[sig]) {
3736  ignoreSig[sig] = ignore;
3737  if (ignore) {
3738  struct sigaction sigact;
3739 #if defined(R__SUN)
3740  sigact.sa_handler = (void (*)())SIG_IGN;
3741 #elif defined(R__SOLARIS)
3742  sigact.sa_handler = (void (*)(int))SIG_IGN;
3743 #else
3744  sigact.sa_handler = SIG_IGN;
3745 #endif
3746  sigemptyset(&sigact.sa_mask);
3747  sigact.sa_flags = 0;
3748  if (sigaction(gSignalMap[sig].fCode, &sigact, &oldsigact[sig]) < 0)
3749  ::SysError("TUnixSystem::UnixIgnoreSignal", "sigaction");
3750  } else {
3751  if (sigaction(gSignalMap[sig].fCode, &oldsigact[sig], 0) < 0)
3752  ::SysError("TUnixSystem::UnixIgnoreSignal", "sigaction");
3753  }
3754  }
3755 }
3756 
3757 ////////////////////////////////////////////////////////////////////////////////
3758 /// When the argument is true the SIGALRM signal handler is set so that
3759 /// interrupted syscalls will not be restarted by the kernel. This is
3760 /// typically used in case one wants to put a timeout on an I/O operation.
3761 /// By default interrupted syscalls will always be restarted (for all
3762 /// signals). This can be controlled for each a-synchronous TTimer via
3763 /// the method TTimer::SetInterruptSyscalls().
3764 
3766 {
3767  if (gSignalMap[kSigAlarm].fHandler) {
3768  struct sigaction sigact;
3769 #if defined(R__SUN)
3770  sigact.sa_handler = (void (*)())sighandler;
3771 #elif defined(R__SOLARIS)
3772  sigact.sa_handler = sighandler;
3773 #elif defined(R__LYNXOS)
3774 # if (__GNUG__>=3)
3775  sigact.sa_handler = sighandler;
3776 # else
3777  sigact.sa_handler = (void (*)(...))sighandler;
3778 # endif
3779 #else
3780  sigact.sa_handler = sighandler;
3781 #endif
3782  sigemptyset(&sigact.sa_mask);
3783  sigact.sa_flags = 0;
3784  if (set) {
3785 #if defined(SA_INTERRUPT) // SunOS
3786  sigact.sa_flags |= SA_INTERRUPT;
3787 #endif
3788  } else {
3789 #if defined(SA_RESTART)
3790  sigact.sa_flags |= SA_RESTART;
3791 #endif
3792  }
3793  if (sigaction(gSignalMap[kSigAlarm].fCode, &sigact, 0) < 0)
3794  ::SysError("TUnixSystem::UnixSigAlarmInterruptsSyscalls", "sigaction");
3795  }
3796 }
3797 
3798 ////////////////////////////////////////////////////////////////////////////////
3799 /// Return the signal name associated with a signal.
3800 
3802 {
3803  return gSignalMap[sig].fSigName;
3804 }
3805 
3806 ////////////////////////////////////////////////////////////////////////////////
3807 /// Restore old signal handler for specified signal.
3808 
3810 {
3811  if (gSignalMap[sig].fOldHandler) {
3812  // restore old signal handler
3813  if (sigaction(gSignalMap[sig].fCode, gSignalMap[sig].fOldHandler, 0) < 0)
3814  ::SysError("TUnixSystem::UnixSignal", "sigaction");
3815  delete gSignalMap[sig].fOldHandler;
3816  gSignalMap[sig].fOldHandler = 0;
3817  gSignalMap[sig].fHandler = 0;
3818  }
3819 }
3820 
3821 ////////////////////////////////////////////////////////////////////////////////
3822 /// Restore old signal handlers.
3823 
3825 {
3826  for (int sig = 0; sig < kMAXSIGNALS; sig++)
3827  UnixResetSignal((ESignals)sig);
3828 }
3829 
3830 //---- time --------------------------------------------------------------------
3831 
3832 ////////////////////////////////////////////////////////////////////////////////
3833 /// Get current time in milliseconds since 0:00 Jan 1 1995.
3834 
3836 {
3837  static std::atomic<time_t> jan95{0};
3838  if (!jan95) {
3839  struct tm tp;
3840  tp.tm_year = 95;
3841  tp.tm_mon = 0;
3842  tp.tm_mday = 1;
3843  tp.tm_hour = 0;
3844  tp.tm_min = 0;
3845  tp.tm_sec = 0;
3846  tp.tm_isdst = -1;
3847 
3848  jan95 = mktime(&tp);
3849  if ((int)jan95 == -1) {
3850  ::SysError("TUnixSystem::UnixNow", "error converting 950001 0:00 to time_t");
3851  return 0;
3852  }
3853  }
3854 
3855  struct timeval t;
3856  gettimeofday(&t, 0);
3857  return Long64_t(t.tv_sec-(Long_t)jan95)*1000 + t.tv_usec/1000;
3858 }
3859 
3860 ////////////////////////////////////////////////////////////////////////////////
3861 /// Set interval timer to time-out in ms milliseconds.
3862 
3864 {
3865  struct itimerval itv;
3866  itv.it_value.tv_sec = 0;
3867  itv.it_value.tv_usec = 0;
3868  itv.it_interval.tv_sec = 0;
3869  itv.it_interval.tv_usec = 0;
3870  if (ms > 0) {
3871  itv.it_value.tv_sec = time_t(ms / 1000);
3872  itv.it_value.tv_usec = time_t((ms % 1000) * 1000);
3873  }
3874  int st = setitimer(ITIMER_REAL, &itv, 0);
3875  if (st == -1)
3876  ::SysError("TUnixSystem::UnixSetitimer", "setitimer");
3877  return st;
3878 }
3879 
3880 //---- file descriptors --------------------------------------------------------
3881 
3882 ////////////////////////////////////////////////////////////////////////////////
3883 /// Wait for events on the file descriptors specified in the readready and
3884 /// writeready masks or for timeout (in milliseconds) to occur. Returns
3885 /// the number of ready descriptors, or 0 in case of timeout, or < 0 in
3886 /// case of an error, with -2 being EINTR and -3 EBADF. In case of EINTR
3887 /// the errno has been reset and the method can be called again.
3888 
3889 int TUnixSystem::UnixSelect(Int_t nfds, TFdSet *readready, TFdSet *writeready,
3890  Long_t timeout)
3891 {
3892  int retcode;
3893 
3894  fd_set *rd = (readready) ? (fd_set*)readready->GetBits() : 0;
3895  fd_set *wr = (writeready) ? (fd_set*)writeready->GetBits() : 0;
3896 
3897  if (timeout >= 0) {
3898  struct timeval tv;
3899  tv.tv_sec = Int_t(timeout / 1000);
3900  tv.tv_usec = (timeout % 1000) * 1000;
3901  retcode = select(nfds, rd, wr, 0, &tv);
3902  } else {
3903  retcode = select(nfds, rd, wr, 0, 0);
3904  }
3905  if (retcode == -1) {
3906  if (GetErrno() == EINTR) {
3907  ResetErrno(); // errno is not self reseting
3908  return -2;
3909  }
3910  if (GetErrno() == EBADF)
3911  return -3;
3912  return -1;
3913  }
3914 
3915  return retcode;
3916 }
3917 
3918 //---- directories -------------------------------------------------------------
3919 
3920 ////////////////////////////////////////////////////////////////////////////////
3921 /// Returns the user's home directory.
3922 
3923 const char *TUnixSystem::UnixHomedirectory(const char *name)
3924 {
3925  static char path[kMAXPATHLEN], mydir[kMAXPATHLEN] = { '\0' };
3926  return UnixHomedirectory(name, path, mydir);
3927 }
3928 
3929 ////////////////////////////////////////////////////////////////////////////
3930 /// Returns the user's home directory.
3931 
3932 const char *TUnixSystem::UnixHomedirectory(const char *name, char *path, char *mydir)
3933 {
3934  struct passwd *pw;
3935  if (name) {
3936  pw = getpwnam(name);
3937  if (pw) {
3938  strncpy(path, pw->pw_dir, kMAXPATHLEN-1);
3939  path[kMAXPATHLEN-1] = '\0';
3940  return path;
3941  }
3942  } else {
3943  if (mydir[0])
3944  return mydir;
3945  pw = getpwuid(getuid());
3946  if (pw && pw->pw_dir) {
3947  strncpy(mydir, pw->pw_dir, kMAXPATHLEN-1);
3948  mydir[kMAXPATHLEN-1] = '\0';
3949  return mydir;
3950  } else if (gSystem->Getenv("HOME")) {
3951  strncpy(mydir, gSystem->Getenv("HOME"), kMAXPATHLEN-1);
3952  mydir[kMAXPATHLEN-1] = '\0';
3953  return mydir;
3954  }
3955  }
3956  return 0;
3957 }
3958 
3959 ////////////////////////////////////////////////////////////////////////////////
3960 /// Make a Unix file system directory. Returns 0 in case of success and
3961 /// -1 if the directory could not be created (either already exists or
3962 /// illegal path name).
3963 
3964 int TUnixSystem::UnixMakedir(const char *dir)
3965 {
3966  return ::mkdir(StripOffProto(dir, "file:"), 0755);
3967 }
3968 
3969 ////////////////////////////////////////////////////////////////////////////////
3970 /// Open a directory.
3971 
3972 void *TUnixSystem::UnixOpendir(const char *dir)
3973 {
3974  struct stat finfo;
3975 
3976  const char *edir = StripOffProto(dir, "file:");
3977 
3978  if (stat(edir, &finfo) < 0)
3979  return 0;
3980 
3981  if (!S_ISDIR(finfo.st_mode))
3982  return 0;
3983 
3984  return (void*) opendir(edir);
3985 }
3986 
3987 #if defined(_POSIX_SOURCE)
3988 // Posix does not require that the d_ino field be present, and some
3989 // systems do not provide it.
3990 # define REAL_DIR_ENTRY(dp) 1
3991 #else
3992 # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
3993 #endif
3994 
3995 ////////////////////////////////////////////////////////////////////////////////
3996 /// Returns the next directory entry.
3997 
3998 const char *TUnixSystem::UnixGetdirentry(void *dirp1)
3999 {
4000  DIR *dirp = (DIR*)dirp1;
4001 #ifdef HAS_DIRENT
4002  struct dirent *dp;
4003 #else
4004  struct direct *dp;
4005 #endif
4006 
4007  if (dirp) {
4008  for (;;) {
4009  dp = readdir(dirp);
4010  if (dp == 0)
4011  return 0;
4012  if (REAL_DIR_ENTRY(dp))
4013  return dp->d_name;
4014  }
4015  }
4016  return 0;
4017 }
4018 
4019 //---- files -------------------------------------------------------------------
4020 
4021 ////////////////////////////////////////////////////////////////////////////////
4022 /// Get info about a file. Info is returned in the form of a FileStat_t
4023 /// structure (see TSystem.h).
4024 /// The function returns 0 in case of success and 1 if the file could
4025 /// not be stat'ed.
4026 
4027 int TUnixSystem::UnixFilestat(const char *fpath, FileStat_t &buf)
4028 {
4029  const char *path = StripOffProto(fpath, "file:");
4030  buf.fIsLink = kFALSE;
4031 
4032 #if defined(R__SEEK64)
4033  struct stat64 sbuf;
4034  if (path && lstat64(path, &sbuf) == 0) {
4035 #else
4036  struct stat sbuf;
4037  if (path && lstat(path, &sbuf) == 0) {
4038 #endif
4039  buf.fIsLink = S_ISLNK(sbuf.st_mode);
4040  if (buf.fIsLink) {
4041 #if defined(R__SEEK64)
4042  if (stat64(path, &sbuf) == -1) {
4043 #else
4044  if (stat(path, &sbuf) == -1) {
4045 #endif
4046  return 1;
4047  }
4048  }
4049  buf.fDev = sbuf.st_dev;
4050  buf.fIno = sbuf.st_ino;
4051  buf.fMode = sbuf.st_mode;
4052  buf.fUid = sbuf.st_uid;
4053  buf.fGid = sbuf.st_gid;
4054  buf.fSize = sbuf.st_size;
4055  buf.fMtime = sbuf.st_mtime;
4056 
4057  return 0;
4058  }
4059  return 1;
4060 }
4061 
4062 ////////////////////////////////////////////////////////////////////////////////
4063 /// Get info about a file system: id, bsize, bfree, blocks.
4064 /// Id is file system type (machine dependend, see statfs())
4065 /// Bsize is block size of file system
4066 /// Blocks is total number of blocks in file system
4067 /// Bfree is number of free blocks in file system
4068 /// The function returns 0 in case of success and 1 if the file system could
4069 /// not be stat'ed.
4070 
4071 int TUnixSystem::UnixFSstat(const char *path, Long_t *id, Long_t *bsize,
4072  Long_t *blocks, Long_t *bfree)
4073 {
4074  struct statfs statfsbuf;
4075 #if (defined(R__SOLARIS) && !defined(R__LINUX))
4076  if (statfs(path, &statfsbuf, sizeof(struct statfs), 0) == 0) {
4077  *id = statfsbuf.f_fstyp;
4078  *bsize = statfsbuf.f_bsize;
4079  *blocks = statfsbuf.f_blocks;
4080  *bfree = statfsbuf.f_bfree;
4081 #else
4082  if (statfs((char*)path, &statfsbuf) == 0) {
4083 #ifdef R__OBSD
4084  // Convert BSD filesystem names to Linux filesystem type numbers
4085  // where possible. Linux statfs uses a value of -1 to indicate
4086  // an unsupported field.
4087 
4088  if (!strcmp(statfsbuf.f_fstypename, MOUNT_FFS) ||
4089  !strcmp(statfsbuf.f_fstypename, MOUNT_MFS))
4090  *id = 0x11954;
4091  else if (!strcmp(statfsbuf.f_fstypename, MOUNT_NFS))
4092  *id = 0x6969;
4093  else if (!strcmp(statfsbuf.f_fstypename, MOUNT_MSDOS))
4094  *id = 0x4d44;
4095  else if (!strcmp(statfsbuf.f_fstypename, MOUNT_PROCFS))
4096  *id = 0x9fa0;
4097  else if (!strcmp(statfsbuf.f_fstypename, MOUNT_EXT2FS))
4098  *id = 0xef53;
4099  else if (!strcmp(statfsbuf.f_fstypename, MOUNT_CD9660))
4100  *id = 0x9660;
4101  else if (!strcmp(statfsbuf.f_fstypename, MOUNT_NCPFS))
4102  *id = 0x6969;
4103  else
4104  *id = -1;
4105 #else
4106  *id = statfsbuf.f_type;
4107 #endif
4108  *bsize = statfsbuf.f_bsize;
4109  *blocks = statfsbuf.f_blocks;
4110  *bfree = statfsbuf.f_bavail;
4111 #endif
4112  return 0;
4113  }
4114  return 1;
4115 }
4116 
4117 ////////////////////////////////////////////////////////////////////////////////
4118 /// Wait till child is finished.
4119 
4121 {
4122  int status;
4123  return (int) waitpid(0, &status, WNOHANG);
4124 }
4125 
4126 //---- RPC -------------------------------------------------------------------
4127 
4128 ////////////////////////////////////////////////////////////////////////////////
4129 /// Open a TCP/IP connection to server and connect to a service (i.e. port).
4130 /// Use tcpwindowsize to specify the size of the receive buffer, it has
4131 /// to be specified here to make sure the window scale option is set (for
4132 /// tcpwindowsize > 65KB and for platforms supporting window scaling).
4133 /// Is called via the TSocket constructor. Returns -1 in case of error.
4134 
4135 int TUnixSystem::UnixTcpConnect(const char *hostname, int port,
4136  int tcpwindowsize)
4137 {
4138  short sport;
4139  struct servent *sp;
4140 
4141  if ((sp = getservbyport(htons(port), kProtocolName)))
4142  sport = sp->s_port;
4143  else
4144  sport = htons(port);
4145 
4146  TInetAddress addr = gSystem->GetHostByName(hostname);
4147  if (!addr.IsValid()) return -1;
4148  UInt_t adr = htonl(addr.GetAddress());
4149 
4150  struct sockaddr_in server;
4151  memset(&server, 0, sizeof(server));
4152  memcpy(&server.sin_addr, &adr, sizeof(adr));
4153  server.sin_family = addr.GetFamily();
4154  server.sin_port = sport;
4155 
4156  // Create socket
4157  int sock;
4158  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
4159  ::SysError("TUnixSystem::UnixTcpConnect", "socket (%s:%d)",
4160  hostname, port);
4161  return -1;
4162  }
4163 
4164  if (tcpwindowsize > 0) {
4165  gSystem->SetSockOpt(sock, kRecvBuffer, tcpwindowsize);
4166  gSystem->SetSockOpt(sock, kSendBuffer, tcpwindowsize);
4167  }
4168 
4169  while (connect(sock, (struct sockaddr*) &server, sizeof(server)) == -1) {
4170  if (GetErrno() == EINTR)
4171  ResetErrno();
4172  else {
4173  ::SysError("TUnixSystem::UnixTcpConnect", "connect (%s:%d)",
4174  hostname, port);
4175  close(sock);
4176  return -1;
4177  }
4178  }
4179  return sock;
4180 }
4181 
4182 
4183 ////////////////////////////////////////////////////////////////////////////////
4184 /// Creates a UDP socket connection
4185 /// Is called via the TSocket constructor. Returns -1 in case of error.
4186 
4187 int TUnixSystem::UnixUdpConnect(const char *hostname, int port)
4188 {
4189  short sport;
4190  struct servent *sp;
4191 
4192  if ((sp = getservbyport(htons(port), kProtocolName)))
4193  sport = sp->s_port;
4194  else
4195  sport = htons(port);
4196 
4197  TInetAddress addr = gSystem->GetHostByName(hostname);
4198  if (!addr.IsValid()) return -1;
4199  UInt_t adr = htonl(addr.GetAddress());
4200 
4201  struct sockaddr_in server;
4202  memset(&server, 0, sizeof(server));
4203  memcpy(&server.sin_addr, &adr, sizeof(adr));
4204  server.sin_family = addr.GetFamily();
4205  server.sin_port = sport;
4206 
4207  // Create socket
4208  int sock;
4209  if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
4210  ::SysError("TUnixSystem::UnixUdpConnect", "socket (%s:%d)",
4211  hostname, port);
4212  return -1;
4213  }
4214 
4215  while (connect(sock, (struct sockaddr*) &server, sizeof(server)) == -1) {
4216  if (GetErrno() == EINTR)
4217  ResetErrno();
4218  else {
4219  ::SysError("TUnixSystem::UnixUdpConnect", "connect (%s:%d)",
4220  hostname, port);
4221  close(sock);
4222  return -1;
4223  }
4224  }
4225  return sock;
4226 }
4227 
4228 ////////////////////////////////////////////////////////////////////////////////
4229 /// Connect to a Unix domain socket.
4230 
4232 {
4233  return UnixUnixConnect(TString::Format("%s/%d", kServerPath, port));
4234 }
4235 
4236 ////////////////////////////////////////////////////////////////////////////////
4237 /// Connect to a Unix domain socket. Returns -1 in case of error.
4238 
4239 int TUnixSystem::UnixUnixConnect(const char *sockpath)
4240 {
4241  if (!sockpath || strlen(sockpath) <= 0) {
4242  ::SysError("TUnixSystem::UnixUnixConnect", "socket path undefined");
4243  return -1;
4244  }
4245 
4246  int sock;
4247  struct sockaddr_un unserver;
4248  unserver.sun_family = AF_UNIX;
4249 
4250  if (strlen(sockpath) > sizeof(unserver.sun_path)-1) {
4251  ::Error("TUnixSystem::UnixUnixConnect", "socket path %s, longer than max allowed length (%u)",
4252  sockpath, (UInt_t)sizeof(unserver.sun_path)-1);
4253  return -1;
4254  }
4255  strcpy(unserver.sun_path, sockpath);
4256 
4257  // Open socket
4258  if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
4259  ::SysError("TUnixSystem::UnixUnixConnect", "socket");
4260  return -1;
4261  }
4262 
4263  while (connect(sock, (struct sockaddr*) &unserver, strlen(unserver.sun_path)+2) == -1) {
4264  if (GetErrno() == EINTR)
4265  ResetErrno();
4266  else {
4267  ::SysError("TUnixSystem::UnixUnixConnect", "connect");
4268  close(sock);
4269  return -1;
4270  }
4271  }
4272  return sock;
4273 }
4274 
4275 ////////////////////////////////////////////////////////////////////////////////
4276 /// Open a socket, bind to it and start listening for TCP/IP connections
4277 /// on the port. If reuse is true reuse the address, backlog specifies
4278 /// how many sockets can be waiting to be accepted. If port is 0 a port
4279 /// scan will be done to find a free port. This option is mutual exlusive
4280 /// with the reuse option.
4281 /// Use tcpwindowsize to specify the size of the receive buffer, it has
4282 /// to be specified here to make sure the window scale option is set (for
4283 /// tcpwindowsize > 65KB and for platforms supporting window scaling).
4284 /// Returns socket fd or -1 if socket() failed, -2 if bind() failed
4285 /// or -3 if listen() failed.
4286 
4287 int TUnixSystem::UnixTcpService(int port, Bool_t reuse, int backlog,
4288  int tcpwindowsize)
4289 {
4290  const short kSOCKET_MINPORT = 5000, kSOCKET_MAXPORT = 15000;
4291  short sport, tryport = kSOCKET_MINPORT;
4292  struct servent *sp;
4293 
4294  if (port == 0 && reuse) {
4295  ::Error("TUnixSystem::UnixTcpService", "cannot do a port scan while reuse is true");
4296  return -1;
4297  }
4298 
4299  if ((sp = getservbyport(htons(port), kProtocolName)))
4300  sport = sp->s_port;
4301  else
4302  sport = htons(port);
4303 
4304  // Create tcp socket
4305  int sock;
4306  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
4307  ::SysError("TUnixSystem::UnixTcpService", "socket");
4308  return -1;
4309  }
4310 
4311  if (reuse)
4312  gSystem->SetSockOpt(sock, kReuseAddr, 1);
4313 
4314  if (tcpwindowsize > 0) {
4315  gSystem->SetSockOpt(sock, kRecvBuffer, tcpwindowsize);
4316  gSystem->SetSockOpt(sock, kSendBuffer, tcpwindowsize);
4317  }
4318 
4319  struct sockaddr_in inserver;
4320  memset(&inserver, 0, sizeof(inserver));
4321  inserver.sin_family = AF_INET;
4322  inserver.sin_addr.s_addr = htonl(INADDR_ANY);
4323  inserver.sin_port = sport;
4324 
4325  // Bind socket
4326  if (port > 0) {
4327  if (::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver))) {
4328  ::SysError("TUnixSystem::UnixTcpService", "bind");
4329  close(sock);
4330  return -2;
4331  }
4332  } else {
4333  int bret;
4334  do {
4335  inserver.sin_port = htons(tryport);
4336  bret = ::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver));
4337  tryport++;
4338  } while (bret < 0 && GetErrno() == EADDRINUSE && tryport < kSOCKET_MAXPORT);
4339  if (bret < 0) {
4340  ::SysError("TUnixSystem::UnixTcpService", "bind (port scan)");
4341  close(sock);
4342  return -2;
4343  }
4344  }
4345 
4346  // Start accepting connections
4347  if (::listen(sock, backlog)) {
4348  ::SysError("TUnixSystem::UnixTcpService", "listen");
4349  close(sock);
4350  return -3;
4351  }
4352 
4353  return sock;
4354 }
4355 
4356 ////////////////////////////////////////////////////////////////////////////////
4357 /// Open a socket, bind to it and start listening for UDP connections
4358 /// on the port. If reuse is true reuse the address, backlog specifies
4359 /// how many sockets can be waiting to be accepted. If port is 0 a port
4360 /// scan will be done to find a free port. This option is mutual exlusive
4361 /// with the reuse option.
4362 
4363 int TUnixSystem::UnixUdpService(int port, int backlog)
4364 {
4365  const short kSOCKET_MINPORT = 5000, kSOCKET_MAXPORT = 15000;
4366  short sport, tryport = kSOCKET_MINPORT;
4367  struct servent *sp;
4368 
4369  if ((sp = getservbyport(htons(port), kProtocolName)))
4370  sport = sp->s_port;
4371  else
4372  sport = htons(port);
4373 
4374  // Create udp socket
4375  int sock;
4376  if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
4377  ::SysError("TUnixSystem::UnixUdpService", "socket");
4378  return -1;
4379  }
4380 
4381  struct sockaddr_in inserver;
4382  memset(&inserver, 0, sizeof(inserver));
4383  inserver.sin_family = AF_INET;
4384  inserver.sin_addr.s_addr = htonl(INADDR_ANY);
4385  inserver.sin_port = sport;
4386 
4387  // Bind socket
4388  if (port > 0) {
4389  if (::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver))) {
4390  ::SysError("TUnixSystem::UnixUdpService", "bind");
4391  close(sock);
4392  return -2;
4393  }
4394  } else {
4395  int bret;
4396  do {
4397  inserver.sin_port = htons(tryport);
4398  bret = ::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver));
4399  tryport++;
4400  } while (bret < 0 && GetErrno() == EADDRINUSE && tryport < kSOCKET_MAXPORT);
4401  if (bret < 0) {
4402  ::SysError("TUnixSystem::UnixUdpService", "bind (port scan)");
4403  close(sock);
4404  return -2;
4405  }
4406  }
4407 
4408  // Start accepting connections
4409  if (::listen(sock, backlog)) {
4410  ::SysError("TUnixSystem::UnixUdpService", "listen");
4411  close(sock);
4412  return -3;
4413  }
4414 
4415  return sock;
4416 }
4417 
4418 ////////////////////////////////////////////////////////////////////////////////
4419 /// Open a socket, bind to it and start listening for Unix domain connections
4420 /// to it. Returns socket fd or -1.
4421 
4422 int TUnixSystem::UnixUnixService(int port, int backlog)
4423 {
4424  int oldumask;
4425 
4426  // Assure that socket directory exists
4427  oldumask = umask(0);
4428  int res = ::mkdir(kServerPath, 0777);
4429  umask(oldumask);
4430 
4431  if (res == -1)
4432  return -1;
4433 
4434  // Socket path
4435  TString sockpath;
4436  sockpath.Form("%s/%d", kServerPath, port);
4437 
4438  // Remove old socket
4439  unlink(sockpath.Data());
4440 
4441  return UnixUnixService(sockpath, backlog);
4442 }
4443 
4444 ////////////////////////////////////////////////////////////////////////////////
4445 /// Open a socket on path 'sockpath', bind to it and start listening for Unix
4446 /// domain connections to it. Returns socket fd or -1.
4447 
4448 int TUnixSystem::UnixUnixService(const char *sockpath, int backlog)
4449 {
4450  if (!sockpath || strlen(sockpath) <= 0) {
4451  ::SysError("TUnixSystem::UnixUnixService", "socket path undefined");
4452  return -1;
4453  }
4454 
4455  struct sockaddr_un unserver;
4456  int sock;
4457 
4458  // Prepare structure
4459  memset(&unserver, 0, sizeof(unserver));
4460  unserver.sun_family = AF_UNIX;
4461 
4462  if (strlen(sockpath) > sizeof(unserver.sun_path)-1) {
4463  ::Error("TUnixSystem::UnixUnixService", "socket path %s, longer than max allowed length (%u)",
4464  sockpath, (UInt_t)sizeof(unserver.sun_path)-1);
4465  return -1;
4466  }
4467  strcpy(unserver.sun_path, sockpath);
4468 
4469  // Create socket
4470  if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
4471  ::SysError("TUnixSystem::UnixUnixService", "socket");
4472  return -1;
4473  }
4474 
4475  if (::bind(sock, (struct sockaddr*) &unserver, strlen(unserver.sun_path)+2)) {
4476  ::SysError("TUnixSystem::UnixUnixService", "bind");
4477  close(sock);
4478  return -1;
4479  }
4480 
4481  // Start accepting connections
4482  if (::listen(sock, backlog)) {
4483  ::SysError("TUnixSystem::UnixUnixService", "listen");
4484  close(sock);
4485  return -1;
4486  }
4487 
4488  return sock;
4489 }
4490 
4491 ////////////////////////////////////////////////////////////////////////////////
4492 /// Receive exactly length bytes into buffer. Returns number of bytes
4493 /// received. Returns -1 in case of error, -2 in case of MSG_OOB
4494 /// and errno == EWOULDBLOCK, -3 in case of MSG_OOB and errno == EINVAL
4495 /// and -4 in case of kNoBlock and errno == EWOULDBLOCK.
4496 /// Returns -5 if pipe broken or reset by peer (EPIPE || ECONNRESET).
4497 
4498 int TUnixSystem::UnixRecv(int sock, void *buffer, int length, int flag)
4499 {
4500  ResetErrno();
4501 
4502  if (sock < 0) return -1;
4503 
4504  int once = 0;
4505  if (flag == -1) {
4506  flag = 0;
4507  once = 1;
4508  }
4509  if (flag == MSG_PEEK)
4510  once = 1;
4511 
4512  int n, nrecv = 0;
4513  char *buf = (char *)buffer;
4514 
4515  for (n = 0; n < length; n += nrecv) {
4516  if ((nrecv = recv(sock, buf+n, length-n, flag)) <= 0) {
4517  if (nrecv == 0)
4518  break; // EOF
4519  if (flag == MSG_OOB) {
4520  if (GetErrno() == EWOULDBLOCK)
4521  return -2;
4522  else if (GetErrno() == EINVAL)
4523  return -3;
4524  }
4525  if (GetErrno() == EWOULDBLOCK)
4526  return -4;
4527  else {
4528  if (GetErrno() != EINTR)
4529  ::SysError("TUnixSystem::UnixRecv", "recv");
4530  if (GetErrno() == EPIPE || GetErrno() == ECONNRESET)
4531  return -5;
4532  else
4533  return -1;
4534  }
4535  }
4536  if (once)
4537  return nrecv;
4538  }
4539  return n;
4540 }
4541 
4542 ////////////////////////////////////////////////////////////////////////////////
4543 /// Send exactly length bytes from buffer. Returns -1 in case of error,
4544 /// otherwise number of sent bytes. Returns -4 in case of kNoBlock and
4545 /// errno == EWOULDBLOCK. Returns -5 if pipe broken or reset by peer
4546 /// (EPIPE || ECONNRESET).
4547 
4548 int TUnixSystem::UnixSend(int sock, const void *buffer, int length, int flag)
4549 {
4550  if (sock < 0) return -1;
4551 
4552  int once = 0;
4553  if (flag == -1) {
4554  flag = 0;
4555  once = 1;
4556  }
4557 
4558  int n, nsent = 0;
4559  const char *buf = (const char *)buffer;
4560 
4561  for (n = 0; n < length; n += nsent) {
4562  if ((nsent = send(sock, buf+n, length-n, flag)) <= 0) {
4563  if (nsent == 0)
4564  break;
4565  if (GetErrno() == EWOULDBLOCK)
4566  return -4;
4567  else {
4568  if (GetErrno() != EINTR)
4569  ::SysError("TUnixSystem::UnixSend", "send");
4570  if (GetErrno() == EPIPE || GetErrno() == ECONNRESET)
4571  return -5;
4572  else
4573  return -1;
4574  }
4575  }
4576  if (once)
4577  return nsent;
4578  }
4579  return n;
4580 }
4581 
4582 //---- Dynamic Loading ---------------------------------------------------------
4583 
4584 ////////////////////////////////////////////////////////////////////////////////
4585 /// Get shared library search path. Static utility function.
4586 
4587 static const char *DynamicPath(const char *newpath = 0, Bool_t reset = kFALSE)
4588 {
4589  static TString dynpath;
4590  static Bool_t initialized = kFALSE;
4591  if (!initialized) {
4592  // force one time initialization of gROOT before we start
4593  // (otherwise it might be done as a side effect of gEnv->GetValue and
4594  // TROOT's initialization will call this routine).
4595  gROOT;
4596  }
4597 
4598  if (newpath) {
4599  dynpath = newpath;
4600  } else if (reset || !initialized) {
4601  initialized = kTRUE;
4602  TString rdynpath = gEnv->GetValue("Root.DynamicPath", (char*)0);
4603  rdynpath.ReplaceAll(": ", ":"); // in case DynamicPath was extended
4604  if (rdynpath.IsNull()) {
4605 #ifdef ROOTLIBDIR
4606  rdynpath = ".:"; rdynpath += ROOTLIBDIR;
4607 #else
4608  rdynpath = ".:"; rdynpath += gRootDir; rdynpath += "/lib";
4609 #endif
4610  }
4611  TString ldpath;
4612 #if defined (R__AIX)
4613  ldpath = gSystem->Getenv("LIBPATH");
4614 #elif defined(R__MACOSX)
4615  ldpath = gSystem->Getenv("DYLD_LIBRARY_PATH");
4616  if (!ldpath.IsNull())
4617  ldpath += ":";
4618  ldpath += gSystem->Getenv("LD_LIBRARY_PATH");
4619  if (!ldpath.IsNull())
4620  ldpath += ":";
4621  ldpath += gSystem->Getenv("DYLD_FALLBACK_LIBRARY_PATH");
4622 #else
4623  ldpath = gSystem->Getenv("LD_LIBRARY_PATH");
4624 #endif
4625  if (ldpath.IsNull())
4626  dynpath = rdynpath;
4627  else {
4628  dynpath = ldpath; dynpath += ":"; dynpath += rdynpath;
4629  }
4630 
4631 #ifdef ROOTLIBDIR
4632  if (!dynpath.Contains(ROOTLIBDIR)) {
4633  dynpath += ":"; dynpath += ROOTLIBDIR;
4634  }
4635 #else
4636  if (!dynpath.Contains(TString::Format("%s/lib", gRootDir))) {
4637  dynpath += ":"; dynpath += gRootDir; dynpath += "/lib";
4638  }
4639 #endif
4640  if (gCling) {
4641  dynpath += ":"; dynpath += gCling->GetSTLIncludePath();
4642  } else
4643  initialized = kFALSE;
4644 
4645 #if defined(R__WINGCC) || defined(R__MACOSX)
4646  if (!dynpath.EndsWith(":")) dynpath += ":";
4647  dynpath += "/usr/local/lib:/usr/X11R6/lib:/usr/lib:/lib:";
4648  dynpath += "/lib/x86_64-linux-gnu:/usr/local/lib64:/usr/lib64:/lib64:";
4649 #else
4650  // trick to get the system search path
4651  std::string cmd("LD_DEBUG=libs LD_PRELOAD=DOESNOTEXIST ls 2>&1");
4652  FILE *pf = popen(cmd.c_str (), "r");
4653  std::string result = "";
4654  char buffer[128];
4655  while (!feof(pf)) {
4656  if (fgets(buffer, 128, pf) != NULL)
4657  result += buffer;
4658  }
4659  pclose(pf);
4660  std::size_t from = result.find("search path=", result.find("(LD_LIBRARY_PATH)"));
4661  std::size_t to = result.find("(system search path)");
4662  if (from != std::string::npos && to != std::string::npos) {
4663  from += 12;
4664  std::string sys_path = result.substr(from, to-from);
4665  sys_path.erase(std::remove_if(sys_path.begin(), sys_path.end(), isspace), sys_path.end());
4666  if (!dynpath.EndsWith(":")) dynpath += ":";
4667  dynpath += sys_path.c_str();
4668  }
4669  dynpath.ReplaceAll("::", ":");
4670 #endif
4671  if (gDebug > 0) std::cout << "dynpath = " << dynpath.Data() << std::endl;
4672  }
4673  return dynpath;
4674 }
4675 
4676 ////////////////////////////////////////////////////////////////////////////////
4677 /// Add a new directory to the dynamic path.
4678 
4679 void TUnixSystem::AddDynamicPath(const char *path)
4680 {
4681  if (path) {
4682  TString oldpath = DynamicPath(0, kFALSE);
4683  oldpath.Append(":");
4684  oldpath.Append(path);
4685  DynamicPath(oldpath);
4686  }
4687 }
4688 
4689 ////////////////////////////////////////////////////////////////////////////////
4690 /// Return the dynamic path (used to find shared libraries).
4691 
4693 {
4694  return DynamicPath(0, kFALSE);
4695 }
4696 
4697 ////////////////////////////////////////////////////////////////////////////////
4698 /// Set the dynamic path to a new value.
4699 /// If the value of 'path' is zero, the dynamic path is reset to its
4700 /// default value.
4701 
4702 void TUnixSystem::SetDynamicPath(const char *path)
4703 {
4704  if (!path)
4705  DynamicPath(0, kTRUE);
4706  else
4707  DynamicPath(path);
4708 }
4709 
4710 ////////////////////////////////////////////////////////////////////////////////
4711 /// Returns the path of a shared library (searches for library in the
4712 /// shared library search path). If no file name extension is provided
4713 /// it first tries .so, .sl, .dl and then .a (for AIX).
4714 
4716 {
4717  char buf[PATH_MAX + 1];
4718  char *res = realpath(sLib.Data(), buf);
4719  if (res) sLib = buf;
4720  TString searchFor = sLib;
4721  if (gSystem->FindFile(GetDynamicPath(), sLib, kReadPermission)) {
4722  return sLib;
4723  }
4724  sLib = searchFor;
4725  const char* lib = sLib.Data();
4726  int len = sLib.Length();
4727  if (len > 3 && (!strcmp(lib+len-3, ".so") ||
4728  !strcmp(lib+len-3, ".dl") ||
4729  !strcmp(lib+len-4, ".dll") ||
4730  !strcmp(lib+len-4, ".DLL") ||
4731  !strcmp(lib+len-6, ".dylib") ||
4732  !strcmp(lib+len-3, ".sl") ||
4733  !strcmp(lib+len-2, ".a"))) {
4734  if (gSystem->FindFile(GetDynamicPath(), sLib, kReadPermission)) {
4735  return sLib;
4736  }
4737  if (!quiet)
4738  Error("FindDynamicLibrary",
4739  "%s does not exist in %s", searchFor.Data(), GetDynamicPath());
4740  return 0;
4741  }
4742  static const char* exts[] = {
4743  ".so", ".dll", ".dylib", ".sl", ".dl", ".a", 0 };
4744  const char** ext = exts;
4745  while (*ext) {
4746  TString fname(sLib);
4747  fname += *ext;
4748  ++ext;
4749  if (gSystem->FindFile(GetDynamicPath(), fname, kReadPermission)) {
4750  sLib.Swap(fname);
4751  return sLib;
4752  }
4753  }
4754 
4755  if (!quiet)
4756  Error("FindDynamicLibrary",
4757  "%s[.so | .dll | .dylib | .sl | .dl | .a] does not exist in %s",
4758  searchFor.Data(), GetDynamicPath());
4759 
4760  return 0;
4761 }
4762 
4763 //---- System, CPU and Memory info ---------------------------------------------
4764 
4765 #if defined(R__MACOSX)
4766 #include <sys/resource.h>
4767 #include <mach/mach.h>
4768 #include <mach/mach_error.h>
4769 
4770 ////////////////////////////////////////////////////////////////////////////////
4771 /// Get system info for Mac OS X.
4772 
4773 static void GetDarwinSysInfo(SysInfo_t *sysinfo)
4774 {
4775  FILE *p = gSystem->OpenPipe("sysctl -n kern.ostype hw.model hw.ncpu hw.cpufrequency "
4776  "hw.busfrequency hw.l2cachesize hw.memsize", "r");
4777  TString s;
4778  s.Gets(p);
4779  sysinfo->fOS = s;
4780  s.Gets(p);
4781  sysinfo->fModel = s;
4782  s.Gets(p);
4783  sysinfo->fCpus = s.Atoi();
4784  s.Gets(p);
4785  Long64_t t = s.Atoll();
4786  sysinfo->fCpuSpeed = Int_t(t / 1000000);
4787  s.Gets(p);
4788  t = s.Atoll();
4789  sysinfo->fBusSpeed = Int_t(t / 1000000);
4790  s.Gets(p);
4791  sysinfo->fL2Cache = s.Atoi() / 1024;
4792  s.Gets(p);
4793  t = s.Atoll();
4794  sysinfo->fPhysRam = Int_t(t / 1024 / 1024);
4795  gSystem->ClosePipe(p);
4796  p = gSystem->OpenPipe("hostinfo", "r");
4797  while (s.Gets(p)) {
4798  if (s.BeginsWith("Processor type: ")) {
4799  TPRegexp("Processor type: ([^ ]+).*").Substitute(s, "$1");
4800  sysinfo->fCpuType = s;
4801  }
4802  }
4803  gSystem->ClosePipe(p);
4804 }
4805 
4806 ////////////////////////////////////////////////////////////////////////////////
4807 /// Get CPU load on Mac OS X.
4808 
4809 static void ReadDarwinCpu(long *ticks)
4810 {
4811  mach_msg_type_number_t count;
4812  kern_return_t kr;
4813  host_cpu_load_info_data_t cpu;
4814 
4815  ticks[0] = ticks[1] = ticks[2] = ticks[3] = 0;
4816 
4817  count = HOST_CPU_LOAD_INFO_COUNT;
4818  kr = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&cpu, &count);
4819  if (kr != KERN_SUCCESS) {
4820  ::Error("TUnixSystem::ReadDarwinCpu", "host_statistics: %s", mach_error_string(kr));
4821  } else {
4822  ticks[0] = cpu.cpu_ticks[CPU_STATE_USER];
4823  ticks[1] = cpu.cpu_ticks[CPU_STATE_SYSTEM];
4824  ticks[2] = cpu.cpu_ticks[CPU_STATE_IDLE];
4825  ticks[3] = cpu.cpu_ticks[CPU_STATE_NICE];
4826  }
4827 }
4828 
4829 ////////////////////////////////////////////////////////////////////////////////
4830 /// Get CPU stat for Mac OS X. Use sampleTime to set the interval over which
4831 /// the CPU load will be measured, in ms (default 1000).
4832 
4833 static void GetDarwinCpuInfo(CpuInfo_t *cpuinfo, Int_t sampleTime)
4834 {
4835  Double_t avg[3];
4836  if (getloadavg(avg, sizeof(avg)) < 0) {
4837  ::Error("TUnixSystem::GetDarwinCpuInfo", "getloadavg failed");
4838  } else {
4839  cpuinfo->fLoad1m = (Float_t)avg[0];
4840  cpuinfo->fLoad5m = (Float_t)avg[1];
4841  cpuinfo->fLoad15m = (Float_t)avg[2];
4842  }
4843 
4844  Long_t cpu_ticks1[4], cpu_ticks2[4];
4845  ReadDarwinCpu(cpu_ticks1);
4846  gSystem->Sleep(sampleTime);
4847  ReadDarwinCpu(cpu_ticks2);
4848 
4849  Long_t userticks = (cpu_ticks2[0] + cpu_ticks2[3]) -
4850  (cpu_ticks1[0] + cpu_ticks1[3]);
4851  Long_t systicks = cpu_ticks2[1] - cpu_ticks1[1];
4852  Long_t idleticks = cpu_ticks2[2] - cpu_ticks1[2];
4853  if (userticks < 0) userticks = 0;
4854  if (systicks < 0) systicks = 0;
4855  if (idleticks < 0) idleticks = 0;
4856  Long_t totalticks = userticks + systicks + idleticks;
4857  if (totalticks) {
4858  cpuinfo->fUser = ((Float_t)(100 * userticks)) / ((Float_t)totalticks);
4859  cpuinfo->fSys = ((Float_t)(100 * systicks)) / ((Float_t)totalticks);
4860  cpuinfo->fTotal = cpuinfo->fUser + cpuinfo->fSys;
4861  cpuinfo->fIdle = ((Float_t)(100 * idleticks)) / ((Float_t)totalticks);
4862  }
4863 }
4864 
4865 ////////////////////////////////////////////////////////////////////////////////
4866 /// Get VM stat for Mac OS X.
4867 
4868 static void GetDarwinMemInfo(MemInfo_t *meminfo)
4869 {
4870  static Int_t pshift = 0;
4871  static DIR *dirp;
4872  vm_statistics_data_t vm_info;
4873  mach_msg_type_number_t count;
4874  kern_return_t kr;
4875  struct dirent *dp;
4876  Long64_t total, used, free, swap_total, swap_used;
4877 
4878  count = HOST_VM_INFO_COUNT;
4879  kr = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_info, &count);
4880  if (kr != KERN_SUCCESS) {
4881  ::Error("TUnixSystem::GetDarwinMemInfo", "host_statistics: %s", mach_error_string(kr));
4882  return;
4883  }
4884  if (pshift == 0) {
4885  for (int psize = getpagesize(); psize > 1; psize >>= 1)
4886  pshift++;
4887  }
4888 
4889  used = (Long64_t)(vm_info.active_count + vm_info.inactive_count + vm_info.wire_count) << pshift;
4890  free = (Long64_t)(vm_info.free_count) << pshift;
4891  total = (Long64_t)(vm_info.active_count + vm_info.inactive_count + vm_info.free_count + vm_info.wire_count) << pshift;
4892 
4893  // Swap is available at same time as mem, so grab values here.
4894  swap_used = vm_info.pageouts << pshift;
4895 
4896  // Figure out total swap. This adds up the size of the swapfiles */
4897  dirp = opendir("/private/var/vm");
4898  if (!dirp)
4899  return;
4900 
4901  swap_total = 0;
4902  while ((dp = readdir(dirp)) != 0) {
4903  struct stat sb;
4904  char fname [MAXNAMLEN];
4905  if (strncmp(dp->d_name, "swapfile", 8))
4906  continue;
4907  strlcpy(fname, "/private/var/vm/",MAXNAMLEN);
4908  strlcat (fname, dp->d_name,MAXNAMLEN);
4909  if (stat(fname, &sb) < 0)
4910  continue;
4911  swap_total += sb.st_size;
4912  }
4913  closedir(dirp);
4914 
4915  meminfo->fMemTotal = (Int_t) (total >> 20); // divide by 1024 * 1024
4916  meminfo->fMemUsed = (Int_t) (used >> 20);
4917  meminfo->fMemFree = (Int_t) (free >> 20);
4918  meminfo->fSwapTotal = (Int_t) (swap_total >> 20);
4919  meminfo->fSwapUsed = (Int_t) (swap_used >> 20);
4920  meminfo->fSwapFree = meminfo->fSwapTotal - meminfo->fSwapUsed;
4921 }
4922 
4923 ////////////////////////////////////////////////////////////////////////////////
4924 /// Get process info for this process on Mac OS X.
4925 /// Code largely taken from:
4926 /// http://www.opensource.apple.com/source/top/top-15/libtop.c
4927 /// The virtual memory usage is slightly over estimated as we don't
4928 /// subtract shared regions, but the value makes more sense
4929 /// then pure vsize, which is useless on 64-bit machines.
4930 
4931 static void GetDarwinProcInfo(ProcInfo_t *procinfo)
4932 {
4933 #ifdef _LP64
4934 #define vm_region vm_region_64
4935 #endif
4936 
4937 // taken from <mach/shared_memory_server.h> which is obsoleted in 10.5
4938 #define GLOBAL_SHARED_TEXT_SEGMENT 0x90000000U
4939 #define GLOBAL_SHARED_DATA_SEGMENT 0xA0000000U
4940 #define SHARED_TEXT_REGION_SIZE 0x10000000
4941 #define SHARED_DATA_REGION_SIZE 0x10000000
4942 
4943  struct rusage ru;
4944  if (getrusage(RUSAGE_SELF, &ru) < 0) {
4945  ::SysError("TUnixSystem::GetDarwinProcInfo", "getrusage failed");
4946  } else {
4947  procinfo->fCpuUser = (Float_t)(ru.ru_utime.tv_sec) +
4948  ((Float_t)(ru.ru_utime.tv_usec) / 1000000.);
4949  procinfo->fCpuSys = (Float_t)(ru.ru_stime.tv_sec) +
4950  ((Float_t)(ru.ru_stime.tv_usec) / 1000000.);
4951  }
4952 
4953  task_basic_info_data_t ti;
4954  mach_msg_type_number_t count;
4955  kern_return_t kr;
4956 
4957  task_t a_task = mach_task_self();
4958 
4959  count = TASK_BASIC_INFO_COUNT;
4960  kr = task_info(a_task, TASK_BASIC_INFO, (task_info_t)&ti, &count);
4961  if (kr != KERN_SUCCESS) {
4962  ::Error("TUnixSystem::GetDarwinProcInfo", "task_info: %s", mach_error_string(kr));
4963  } else {
4964  // resident size does not require any calculation. Virtual size
4965  // needs to be adjusted if traversing memory objects do not include the
4966  // globally shared text and data regions
4967  mach_port_t object_name;
4968  vm_address_t address;
4969  vm_region_top_info_data_t info;
4970  vm_size_t vsize, vprvt, rsize, size;
4971  rsize = ti.resident_size;
4972  vsize = ti.virtual_size;
4973  vprvt = 0;
4974  for (address = 0; ; address += size) {
4975  // get memory region
4976  count = VM_REGION_TOP_INFO_COUNT;
4977  if (vm_region(a_task, &address, &size,
4978  VM_REGION_TOP_INFO, (vm_region_info_t)&info, &count,
4979  &object_name) != KERN_SUCCESS) {
4980  // no more memory regions.
4981  break;
4982  }
4983 
4984  if (address >= GLOBAL_SHARED_TEXT_SEGMENT &&
4985  address < (GLOBAL_SHARED_DATA_SEGMENT + SHARED_DATA_REGION_SIZE)) {
4986  // This region is private shared.
4987  // Check if this process has the globally shared
4988  // text and data regions mapped in. If so, adjust
4989  // virtual memory size and exit loop.
4990  if (info.share_mode == SM_EMPTY) {
4991  vm_region_basic_info_data_64_t b_info;
4992  count = VM_REGION_BASIC_INFO_COUNT_64;
4993  if (vm_region_64(a_task, &address,
4994  &size, VM_REGION_BASIC_INFO,
4995  (vm_region_info_t)&b_info, &count,
4996  &object_name) != KERN_SUCCESS) {
4997  break;
4998  }
4999 
5000  if (b_info.reserved) {
5001  vsize -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
5002  //break; // only for vsize
5003  }
5004  }
5005  // Short circuit the loop if this isn't a shared
5006  // private region, since that's the only region
5007  // type we care about within the current address range.
5008  if (info.share_mode != SM_PRIVATE) {
5009  continue;
5010  }
5011  }
5012  switch (info.share_mode) {
5013  case SM_COW: {
5014  if (info.ref_count == 1) {
5015  vprvt += size;
5016  } else {
5017  vprvt += info.private_pages_resident * getpagesize();
5018  }
5019  break;
5020  }
5021  case SM_PRIVATE: {
5022  vprvt += size;
5023  break;
5024  }
5025  default:
5026  break;
5027  }
5028  }
5029 
5030  procinfo->fMemResident = (Long_t)(rsize / 1024);
5031  //procinfo->fMemVirtual = (Long_t)(vsize / 1024);
5032  procinfo->fMemVirtual = (Long_t)(vprvt / 1024);
5033  }
5034 }
5035 #endif
5036 
5037 #if defined(R__LINUX)
5038 ////////////////////////////////////////////////////////////////////////////////
5039 /// Get system info for Linux. Only fBusSpeed is not set.
5040 
5041 static void GetLinuxSysInfo(SysInfo_t *sysinfo)
5042 {
5043  TString s;
5044  FILE *f = fopen("/proc/cpuinfo", "r");
5045  if (f) {
5046  while (s.Gets(f)) {
5047  if (s.BeginsWith("model name")) {
5048  TPRegexp("^.+: *(.*$)").Substitute(s, "$1");
5049  sysinfo->fModel = s;
5050  }
5051  if (s.BeginsWith("cpu MHz")) {
5052  TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5053  sysinfo->fCpuSpeed = s.Atoi();
5054  }
5055  if (s.BeginsWith("cache size")) {
5056  TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5057  sysinfo->fL2Cache = s.Atoi();
5058  }
5059  if (s.BeginsWith("processor")) {
5060  TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5061  sysinfo->fCpus = s.Atoi();
5062  sysinfo->fCpus++;
5063  }
5064  }
5065  fclose(f);
5066  }
5067 
5068  f = fopen("/proc/meminfo", "r");
5069  if (f) {
5070  while (s.Gets(f)) {
5071  if (s.BeginsWith("MemTotal")) {
5072  TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5073  sysinfo->fPhysRam = (s.Atoi() / 1024);
5074  break;
5075  }
5076  }
5077  fclose(f);
5078  }
5079 
5080  f = gSystem->OpenPipe("uname -s -p", "r");
5081  if (f) {
5082  s.Gets(f);
5083  Ssiz_t from = 0;
5084  s.Tokenize(sysinfo->fOS, from);
5085  s.Tokenize(sysinfo->fCpuType, from);
5086  gSystem->ClosePipe(f);
5087  }
5088 }
5089 
5090 ////////////////////////////////////////////////////////////////////////////////
5091 /// Get CPU load on Linux.
5092 
5093 static void ReadLinuxCpu(long *ticks)
5094 {
5095  ticks[0] = ticks[1] = ticks[2] = ticks[3] = 0;
5096 
5097  TString s;
5098  FILE *f = fopen("/proc/stat", "r");
5099  if (!f) return;
5100  s.Gets(f);
5101  // user, user nice, sys, idle
5102  sscanf(s.Data(), "%*s %ld %ld %ld %ld", &ticks[0], &ticks[3], &ticks[1], &ticks[2]);
5103  fclose(f);
5104 }
5105 
5106 ////////////////////////////////////////////////////////////////////////////////
5107 /// Get CPU stat for Linux. Use sampleTime to set the interval over which
5108 /// the CPU load will be measured, in ms (default 1000).
5109 
5110 static void GetLinuxCpuInfo(CpuInfo_t *cpuinfo, Int_t sampleTime)
5111 {
5112  Double_t avg[3] = { -1., -1., -1. };
5113 #ifndef R__WINGCC
5114  if (getloadavg(avg, sizeof(avg)) < 0) {
5115  ::Error("TUnixSystem::GetLinuxCpuInfo", "getloadavg failed");
5116  } else
5117 #endif
5118  {
5119  cpuinfo->fLoad1m = (Float_t)avg[0];
5120  cpuinfo->fLoad5m = (Float_t)avg[1];
5121  cpuinfo->fLoad15m = (Float_t)avg[2];
5122  }
5123 
5124  Long_t cpu_ticks1[4], cpu_ticks2[4];
5125  ReadLinuxCpu(cpu_ticks1);
5126  gSystem->Sleep(sampleTime);
5127  ReadLinuxCpu(cpu_ticks2);
5128 
5129  Long_t userticks = (cpu_ticks2[0] + cpu_ticks2[3]) -
5130  (cpu_ticks1[0] + cpu_ticks1[3]);
5131  Long_t systicks = cpu_ticks2[1] - cpu_ticks1[1];
5132  Long_t idleticks = cpu_ticks2[2] - cpu_ticks1[2];
5133  if (userticks < 0) userticks = 0;
5134  if (systicks < 0) systicks = 0;
5135  if (idleticks < 0) idleticks = 0;
5136  Long_t totalticks = userticks + systicks + idleticks;
5137  if (totalticks) {
5138  cpuinfo->fUser = ((Float_t)(100 * userticks)) / ((Float_t)totalticks);
5139  cpuinfo->fSys = ((Float_t)(100 * systicks)) / ((Float_t)totalticks);
5140  cpuinfo->fTotal = cpuinfo->fUser + cpuinfo->fSys;
5141  cpuinfo->fIdle = ((Float_t)(100 * idleticks)) / ((Float_t)totalticks);
5142  }
5143 }
5144 
5145 ////////////////////////////////////////////////////////////////////////////////
5146 /// Get VM stat for Linux.
5147 
5148 static void GetLinuxMemInfo(MemInfo_t *meminfo)
5149 {
5150  TString s;
5151  FILE *f = fopen("/proc/meminfo", "r");
5152  if (!f) return;
5153  while (s.Gets(f)) {
5154  if (s.BeginsWith("MemTotal")) {
5155  TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5156  meminfo->fMemTotal = (s.Atoi() / 1024);
5157  }
5158  if (s.BeginsWith("MemFree")) {
5159  TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5160  meminfo->fMemFree = (s.Atoi() / 1024);
5161  }
5162  if (s.BeginsWith("SwapTotal")) {
5163  TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5164  meminfo->fSwapTotal = (s.Atoi() / 1024);
5165  }
5166  if (s.BeginsWith("SwapFree")) {
5167  TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5168  meminfo->fSwapFree = (s.Atoi() / 1024);
5169  }
5170  }
5171  fclose(f);
5172 
5173  meminfo->fMemUsed = meminfo->fMemTotal - meminfo->fMemFree;
5174  meminfo->fSwapUsed = meminfo->fSwapTotal - meminfo->fSwapFree;
5175 }
5176 
5177 ////////////////////////////////////////////////////////////////////////////////
5178 /// Get process info for this process on Linux.
5179 
5180 static void GetLinuxProcInfo(ProcInfo_t *procinfo)
5181 {
5182  struct rusage ru;
5183  if (getrusage(RUSAGE_SELF, &ru) < 0) {
5184  ::SysError("TUnixSystem::GetLinuxProcInfo", "getrusage failed");
5185  } else {
5186  procinfo->fCpuUser = (Float_t)(ru.ru_utime.tv_sec) +
5187  ((Float_t)(ru.ru_utime.tv_usec) / 1000000.);
5188  procinfo->fCpuSys = (Float_t)(ru.ru_stime.tv_sec) +
5189  ((Float_t)(ru.ru_stime.tv_usec) / 1000000.);
5190  }
5191 
5192  procinfo->fMemVirtual = -1;
5193  procinfo->fMemResident = -1;
5194  TString s;
5195  FILE *f = fopen(TString::Format("/proc/%d/statm", gSystem->GetPid()), "r");
5196  if (f) {
5197  s.Gets(f);
5198  fclose(f);
5199  Long_t total, rss;
5200  sscanf(s.Data(), "%ld %ld", &total, &rss);
5201  procinfo->fMemVirtual = total * (getpagesize() / 1024);
5202  procinfo->fMemResident = rss * (getpagesize() / 1024);
5203  }
5204 }
5205 #endif
5206 
5207 ////////////////////////////////////////////////////////////////////////////////
5208 /// Returns static system info, like OS type, CPU type, number of CPUs
5209 /// RAM size, etc into the SysInfo_t structure. Returns -1 in case of error,
5210 /// 0 otherwise.
5211 
5213 {
5214  if (!info) return -1;
5215 
5216  static SysInfo_t sysinfo;
5217 
5218  if (!sysinfo.fCpus) {
5219 #if defined(R__MACOSX)
5220  GetDarwinSysInfo(&sysinfo);
5221 #elif defined(R__LINUX)
5222  GetLinuxSysInfo(&sysinfo);
5223 #endif
5224  }
5225 
5226  *info = sysinfo;
5227 
5228  return 0;
5229 }
5230 
5231 ////////////////////////////////////////////////////////////////////////////////
5232 /// Returns cpu load average and load info into the CpuInfo_t structure.
5233 /// Returns -1 in case of error, 0 otherwise. Use sampleTime to set the
5234 /// interval over which the CPU load will be measured, in ms (default 1000).
5235 
5236 int TUnixSystem::GetCpuInfo(CpuInfo_t *info, Int_t sampleTime) const
5237 {
5238  if (!info) return -1;
5239 
5240 #if defined(R__MACOSX)
5241  GetDarwinCpuInfo(info, sampleTime);
5242 #elif defined(R__LINUX)
5243  GetLinuxCpuInfo(info, sampleTime);
5244 #endif
5245 
5246  return 0;
5247 }
5248 
5249 ////////////////////////////////////////////////////////////////////////////////
5250 /// Returns ram and swap memory usage info into the MemInfo_t structure.
5251 /// Returns -1 in case of error, 0 otherwise.
5252 
5254 {
5255  if (!info) return -1;
5256 
5257 #if defined(R__MACOSX)
5258  GetDarwinMemInfo(info);
5259 #elif defined(R__LINUX)
5260  GetLinuxMemInfo(info);
5261 #endif
5262 
5263  return 0;
5264 }
5265 
5266 ////////////////////////////////////////////////////////////////////////////////
5267 /// Returns cpu and memory used by this process into the ProcInfo_t structure.
5268 /// Returns -1 in case of error, 0 otherwise.
5269 
5271 {
5272  if (!info) return -1;
5273 
5274 #if defined(R__MACOSX)
5275  GetDarwinProcInfo(info);
5276 #elif defined(R__LINUX)
5277  GetLinuxProcInfo(info);
5278 #endif
5279 
5280  return 0;
5281 }
Bool_t IsPathLocal(const char *path)
Returns TRUE if the url in &#39;path&#39; points to the local file system.
Int_t fMemFree
Definition: TSystem.h:193
const char * TempDirectory() const
Return a user configured or systemwide directory to create temporary files in.
Int_t fGid
Definition: TSystem.h:151
void(* SigHandler_t)(ESignals)
Definition: TUnixSystem.h:34
int GetPid()
Get process id.
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:929
TString fStdErrTty
Definition: TSystem.h:217
int GetFsInfo(const char *path, Long_t *id, Long_t *bsize, Long_t *blocks, Long_t *bfree)
Get info about a file system: id, bsize, bfree, blocks.
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1265
Float_t fLoad15m
Definition: TSystem.h:179
double read(const std::string &file_name)
reading
void AddTimer(TTimer *ti)
Add timer to list of system timers.
virtual void SetWriteReady()
void ListSymbols(const char *module, const char *re="")
List symbols in a shared library.
virtual int GetPid()
Get process id.
Definition: TSystem.cxx:712
An array of TObjects.
Definition: TObjArray.h:39
void StackTrace()
Print a stack trace.
Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
int pw_uid
Definition: TWinNTSystem.h:52
int GetErrno()
return errno
virtual Bool_t Notify()
Notify when event occurred on descriptor associated with this handler.
virtual Bool_t IsPathLocal(const char *path)
Returns TRUE if the url in &#39;path&#39; points to the local file system.
Definition: TSystem.cxx:1274
long long Long64_t
Definition: RtypesCore.h:69
Int_t fBusSpeed
Definition: TSystem.h:167
int GetMemInfo(MemInfo_t *info) const
Returns ram and swap memory usage info into the MemInfo_t structure.
Int_t fPhysRam
Definition: TSystem.h:169
const char * GetError()
Return system error string.
Int_t fReadOffSet
Definition: TSystem.h:220
Bool_t IsSync() const
virtual const char * WorkingDirectory()
Return working directory.
Definition: TSystem.cxx:866
void Sleep(UInt_t milliSec)
Sleep milliSec milliseconds.
char * pw_shell
Definition: TWinNTSystem.h:57
Bool_t Init()
Initialize Unix system interface.
const char * FindFile(const char *search, TString &file, EAccessMode mode=kFileExists)
Find location of file "wfil" in a search path.
Float_t fSys
Definition: TSystem.h:181
static void UnixResetSignal(ESignals sig)
Restore old signal handler for specified signal.
Bool_t ExpandPathName(TString &patbuf)
Expand a pathname getting rid of special shell characters like ~.
double write(int n, const std::string &file_name, const std::string &vector_type, int compress=0)
writing
std::string GetWorkingDirectory() const
Return working directory.
virtual ~TUnixSystem()
Reset to original state.
static const char * GetExePath()
R__EXTERN TVirtualMutex * gSystemMutex
Definition: TSystem.h:236
Ssiz_t Length() const
Definition: TString.h:390
TLine * line
void Fatal(const char *location, const char *msgfmt,...)
Collectable string class.
Definition: TObjString.h:32
float Float_t
Definition: RtypesCore.h:53
int gr_gid
Definition: TWinNTSystem.h:64
int GetPathInfo(const char *path, FileStat_t &buf)
Get info about a file.
static int UnixFilestat(const char *path, FileStat_t &buf)
Get info about a file.
Int_t GetFPEMask()
Return the bitmap of conditions that trigger a floating point exception.
static int UnixTcpConnect(const char *hostname, int port, int tcpwindowsize)
Open a TCP/IP connection to server and connect to a service (i.e.
#define HOWMANY(x, y)
TString fOS
Definition: TSystem.h:162
static int UnixRecv(int sock, void *buf, int len, int flag)
Receive exactly length bytes into buffer.
int GetSockOpt(int sock, int option, int *val)
Get socket option.
Int_t fUid
Definition: TSystem.h:139
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
int GetPathInfo(const char *path, Long_t *id, Long_t *size, Long_t *flags, Long_t *modtime)
Get info about a file: id, size, flags, modification time.
Definition: TSystem.cxx:1363
Bool_t DispatchTimers(Bool_t mode)
Handle and dispatch timers.
const char * FindDynamicLibrary(TString &lib, Bool_t quiet=kFALSE)
Returns the path of a shared library (searches for library in the shared library search path)...
void demangle(char *_codeInfo, TString &_str)
demangle symbols
TH1 * h
Definition: legend2.C:5
TString fStdOutTty
Definition: TSystem.h:216
char * gr_name
Definition: TWinNTSystem.h:62
TString fGroup
Definition: TSystem.h:153
int Symlink(const char *from, const char *to)
Create a symlink from file1 to file2.
This class represents an Internet Protocol (IP) address.
Definition: TInetAddress.h:40
virtual int MakeDirectory(const char *name)
Make a directory.
Definition: TSystem.cxx:822
virtual void AddSignalHandler(TSignalHandler *sh)
Add a signal handler to list of system signal handlers.
Definition: TSystem.cxx:537
int MakeDirectory(const char *name)
Make a Unix file system directory.
Regular expression class.
Definition: TRegexp.h:35
#define sym(otri1, otri2)
Definition: triangle.c:932
Int_t fStdOutDup
Definition: TSystem.h:218
#define gROOT
Definition: TROOT.h:364
Int_t Select(TList *active, Long_t timeout)
Select on file descriptors.
Int_t GetGid(const char *group=0)
Returns the group&#39;s id. If group = 0, returns current user&#39;s group.
static Long64_t UnixNow()
Get current time in milliseconds since 0:00 Jan 1 1995.
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition: TSystem.cxx:1818
Basic string class.
Definition: TString.h:137
void SetProgname(const char *name)
Set the application name (from command line, argv[0]) and copy it in gProgName.
static struct Signalmap_t gSignalMap[kMAXSIGNALS]
TFileHandler * RemoveFileHandler(TFileHandler *fh)
Remove a file handler from the list of file handlers.
int Int_t
Definition: RtypesCore.h:41
virtual const char * DirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:997
bool Bool_t
Definition: RtypesCore.h:59
virtual TTimer * RemoveTimer(TTimer *t)
Remove timer from list of system timers.
Definition: TSystem.cxx:486
TArc * a
Definition: textangle.C:12
const Bool_t kFALSE
Definition: Rtypes.h:92
Int_t Substitute(TString &s, const TString &replace, const TString &mods="", Int_t start=0, Int_t nMatchMax=10)
Substitute replaces the string s by a new string in which matching patterns are replaced by the repla...
Definition: TPRegexp.cxx:469
const char * HostName()
Return the system&#39;s host name.
int SendRaw(int sock, const void *buffer, int length, int flag)
Send exactly length bytes from buffer.
int Umask(Int_t mask)
Set the process file creation mode mask.
#define gInterpreter
Definition: TInterpreter.h:515
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1511
void Break(const char *location, const char *msgfmt,...)
Long_t fMtime
Definition: TSystem.h:142
void Syslog(ELogLevel level, const char *mess)
Send mess to syslog daemon.
virtual FILE * OpenPipe(const char *command, const char *mode)
Open a pipe.
Definition: TSystem.cxx:667
#define REAL_DIR_ENTRY(dp)
virtual void ResetReadyMask()
TString & Prepend(const char *cs)
Definition: TString.h:604
R__EXTERN TApplication * gApplication
Definition: TApplication.h:171
Basic time type with millisecond precision.
Definition: TTime.h:29
static void UnixSigAlarmInterruptsSyscalls(Bool_t set)
When the argument is true the SIGALRM signal handler is set so that interrupted syscalls will not be ...
int ConnectService(const char *server, int port, int tcpwindowsize, const char *protocol="tcp")
Connect to service servicename on server servername.
const char * HomeDirectory(const char *userName=0)
Return the user&#39;s home directory.
const char * kShellMeta
TString fModel
Definition: TSystem.h:163
#define malloc
Definition: civetweb.c:818
Long64_t fSize
Definition: TSystem.h:141
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:558
void Exit(int code, Bool_t mode=kTRUE)
Exit the application.
int Unlink(const char *name)
Unlink, i.e.
Int_t fUid
Definition: TSystem.h:150
const char * kProtocolName
#define UTMP_FILE
static int UnixSelect(Int_t nfds, TFdSet *readready, TFdSet *writeready, Long_t timeout)
Wait for events on the file descriptors specified in the readready and writeready masks or for timeou...
virtual TFileHandler * RemoveFileHandler(TFileHandler *fh)
Remove a file handler from the list of file handlers.
Definition: TSystem.cxx:569
void Reset()
Definition: TCollection.h:161
void SysError(const char *location, const char *msgfmt,...)
virtual const char * FindFile(const char *search, TString &file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1501
static Int_t GetErrno()
Static function returning system error number.
Definition: TSystem.cxx:265
Int_t fMode
Definition: TSystem.h:138
const char * String
Definition: TXMLSetup.cxx:94
const char * Data() const
Definition: TString.h:349
virtual Bool_t Notify()
Notify when signal occurs.
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:848
virtual int Unlink(const char *name)
Unlink, i.e. remove, a file.
Definition: TSystem.cxx:1346
Int_t Exec(const char *shellcmd)
Execute a command.
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2335
void DispatchOneEvent(Bool_t pendingOnly=kFALSE)
Dispatch a single event.
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition: TSystem.cxx:442
Float_t fUser
Definition: TSystem.h:180
Bool_t IsValid() const
Definition: TInetAddress.h:80
void AddSignalHandler(TSignalHandler *sh)
Add a signal handler to list of system signal handlers.
Int_t fSwapFree
Definition: TSystem.h:196
static int UnixSend(int sock, const void *buf, int len, int flag)
Send exactly length bytes from buffer.
Int_t bsize[]
Definition: SparseFit4.cxx:31
const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Int_t SetFPEMask(Int_t mask=kDefaultMask)
Set which conditions trigger a floating point exception.
static const char * DynamicPath(const char *newpath=0, Bool_t reset=kFALSE)
Get shared library search path. Static utility function.
TObject * Next()
Return next object in collection.
R__EXTERN TFileHandler * gXDisplay
Definition: TSystem.h:550
TString fShell
Definition: TSystem.h:156
static TString * ReadString(TBuffer &b, const TClass *clReq)
Read TString object from buffer.
Definition: TString.cxx:1259
TString fRealName
Definition: TSystem.h:155
static int UnixSetitimer(Long_t ms)
Set interval timer to time-out in ms milliseconds.
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1627
virtual void ListLibraries(const char *regexp="")
List all loaded shared libraries.
Definition: TSystem.cxx:2011
static void UnixResetSignals()
Restore old signal handlers.
FILE * OpenPipe(const char *shellcmd, const char *mode)
Open a pipe.
TString & Append(const char *cs)
Definition: TString.h:492
TInetAddress GetHostByName(const char *server)
Get Internet Protocol (IP) address of host.
int AcceptConnection(int sock)
Accept a connection.
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1965
virtual void Unload(const char *module)
Unload a shared library.
Definition: TSystem.cxx:1990
char * pw_name
Definition: TWinNTSystem.h:50
virtual TInetAddress GetHostByName(const char *server)
Get Internet Protocol (IP) address of host.
Definition: TSystem.cxx:2245
int CopyFile(const char *from, const char *to, Bool_t overwrite=kFALSE)
Copy a file.
void Error(const char *location, const char *msgfmt,...)
void ResetSignals()
Reset signals handlers to previous behaviour.
int SetSockOpt(int sock, int option, int val)
Set socket option.
Int_t fGid
Definition: TSystem.h:140
UInt_t GetAddress() const
Definition: TInetAddress.h:72
ELogLevel
Definition: TSystem.h:66
const Int_t kNFDBITS
A doubly linked list.
Definition: TList.h:47
Float_t fLoad1m
Definition: TSystem.h:177
char ** Argv() const
Definition: TApplication.h:142
static void SigHandler(ESignals sig)
Unix signal handler.
Int_t fL2Cache
Definition: TSystem.h:168
int GetFd() const
TTimer * RemoveTimer(TTimer *ti)
Remove timer from list of system timers.
virtual Bool_t WriteNotify()
Notify when something can be written to the descriptor associated with this handler.
R__EXTERN const char * gProgName
Definition: TSystem.h:234
int GetCpuInfo(CpuInfo_t *info, Int_t sampleTime=1000) const
Returns cpu load average and load info into the CpuInfo_t structure.
Float_t fCpuUser
Definition: TSystem.h:204
ESignals
char * pw_gecos
Definition: TWinNTSystem.h:55
static const char * UnixHomedirectory(const char *user=0)
Returns the user&#39;s home directory.
Bool_t IsActive() const
TString fUser
Definition: TSystem.h:152
static void sighandler(int sig)
Call the signal handler associated with the signal.
void FreeDirectory(void *dirp)
Close a Unix file system directory.
void ResetErrno()
reset errno
virtual void Setenv(const char *name, const char *value)
Set environment variable.
Definition: TSystem.cxx:1611
Int_t fCpus
Definition: TSystem.h:165
virtual Bool_t HasWriteInterest()
True if handler is interested in write events.
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2221
virtual Bool_t Init()
Initialize the OS interface.
Definition: TSystem.cxx:187
int Chmod(const char *file, UInt_t mode)
Set the file permission bits. Returns -1 in case or error, 0 otherwise.
Bool_t fIsLink
Definition: TSystem.h:143
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
void FillWithCwd(char *cwd) const
Fill buffer with current working directory.
int Utime(const char *file, Long_t modtime, Long_t actime)
Set a files modification and access times.
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:496
TInetAddress GetSockName(int sock)
Get Internet Protocol (IP) address of host and port #.
Int_t fSwapUsed
Definition: TSystem.h:195
Bool_t Gets(FILE *fp, Bool_t chop=kTRUE)
Read one line from the stream, including the , or until EOF.
Definition: Stringio.cxx:198
const char * kServerPath
Long_t fMemVirtual
Definition: TSystem.h:207
virtual void SetReadReady()
std::string GetHomeDirectory(const char *userName=0) const
Return the user&#39;s home directory.
void CloseConnection(int sock, Bool_t force=kFALSE)
Close socket.
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2322
void Closelog()
Close connection to system log daemon.
unsigned int UInt_t
Definition: RtypesCore.h:42
TMarker * m
Definition: textangle.C:8
char * Form(const char *fmt,...)
void SetDisplay()
Set DISPLAY environment variable based on utmp entry. Only for UNIX.
Definition: TSocket.h:68
Handles synchronous and a-synchronous timer events.
Definition: TTimer.h:57
Bool_t CheckTimer(const TTime &now)
Check if timer timed out.
Definition: TTimer.cxx:128
Float_t fLoad5m
Definition: TSystem.h:178
Bool_t CheckDescriptors()
Check if there is activity on some file descriptors and call their Notify() member.
TSubString Strip(EStripType s=kTrailing, char c= ' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1070
Func_t DynFindSymbol(const char *module, const char *entry)
dynamic linking of module
static int UnixWaitchild()
Wait till child is finished.
void * OpenDirectory(const char *name)
Open a Unix file system directory. Returns 0 if directory does not exist.
static int UnixUnixService(int port, int backlog)
Open a socket, bind to it and start listening for Unix domain connections to it.
static const char * UnixSigname(ESignals sig)
Return the signal name associated with a signal.
Bool_t IsNull() const
Definition: TString.h:387
Int_t RedirectOutput(const char *name, const char *mode="a", RedirectHandle_t *h=0)
Redirect standard output (stdout, stderr) to the specified file.
static int UnixFSstat(const char *path, Long_t *id, Long_t *bsize, Long_t *blocks, Long_t *bfree)
Get info about a file system: id, bsize, bfree, blocks.
void Warning(const char *location, const char *msgfmt,...)
TString & String()
Definition: TObjString.h:52
const char * GetDynamicPath()
Return the dynamic path (used to find shared libraries).
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition: TSystem.cxx:840
virtual int ClosePipe(FILE *pipe)
Close the pipe.
Definition: TSystem.cxx:676
TGraphErrors * gr
Definition: legend1.C:25
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2241
Int_t GetUid(const char *user=0)
Returns the user&#39;s id. If user = 0, returns current user&#39;s id.
#define Printf
Definition: TGeoToOCC.h:18
int GetProcInfo(ProcInfo_t *info) const
Returns cpu and memory used by this process into the ProcInfo_t structure.
void Unsetenv(const char *name)
Unset environment variable.
UserGroup_t * GetGroupInfo(Int_t gid)
Returns all group info in the UserGroup_t structure.
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2514
#define R__LOCKGUARD2(mutex)
virtual int SetSockOpt(int sock, int kind, int val)
Set socket option.
Definition: TSystem.cxx:2390
static void UnixSignal(ESignals sig, SigHandler_t h)
Set a signal handler for a signal.
static unsigned int total
TString & Remove(Ssiz_t pos)
Definition: TString.h:616
long Long_t
Definition: RtypesCore.h:50
int Ssiz_t
Definition: RtypesCore.h:63
TString fPasswd
Definition: TSystem.h:154
const char * Getenv(const char *name)
Get environment variable.
virtual TSignalHandler * RemoveSignalHandler(TSignalHandler *sh)
Remove a signal handler from list of signal handlers.
Definition: TSystem.cxx:547
static int UnixMakedir(const char *name)
Make a Unix file system directory.
static int UnixUdpService(int port, int backlog)
Open a socket, bind to it and start listening for UDP connections on the port.
R__EXTERN const char * gProgPath
Definition: TSystem.h:235
TString & Swap(TString &other)
Definition: TString.h:647
#define ClassImp(name)
Definition: Rtypes.h:279
double f(double x)
#define STRUCT_UTMP
Float_t fCpuSys
Definition: TSystem.h:205
Int_t GetEffectiveUid()
Returns the effective user id.
static int UnixUnixConnect(int port)
Connect to a Unix domain socket.
virtual Func_t DynFindSymbol(const char *module, const char *entry)
Find specific entry point in specified library.
Definition: TSystem.cxx:1982
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:416
static int UnixTcpService(int port, Bool_t reuse, int backlog, int tcpwindowsize)
Open a socket, bind to it and start listening for TCP/IP connections on the port. ...
const Int_t kFDSETSIZE
double Double_t
Definition: RtypesCore.h:55
int RecvRaw(int sock, void *buffer, int length, int flag)
Receive exactly length bytes into buffer.
Long64_t Atoll() const
Return long long value of string.
Definition: TString.cxx:1991
int RecvBuf(int sock, void *buffer, int length)
Receive a buffer headed by a length indicator.
ELogFacility
Definition: TSystem.h:77
Int_t GetFamily() const
Definition: TInetAddress.h:76
int Rename(const char *from, const char *to)
Rename a file. Returns 0 when successful, -1 in case of failure.
int AnnounceTcpService(int port, Bool_t reuse, int backlog, int tcpwindowsize=-1)
Announce TCP/IP service.
int type
Definition: TGX11.cxx:120
R__EXTERN TEnv * gEnv
Definition: TEnv.h:174
void CheckChilds()
Check if children have finished.
TString fCpuType
Definition: TSystem.h:164
#define free
Definition: civetweb.c:821
unsigned long ULong_t
Definition: RtypesCore.h:51
double func(double *x, double *p)
Definition: stressTF1.cxx:213
static void UnixIgnoreSignal(ESignals sig, Bool_t ignore)
If ignore is true ignore the specified signal, else restore previous behaviour.
Bool_t IsSync() const
Definition: TTimer.h:86
static void * UnixOpendir(const char *name)
Open a directory.
Definition: TSocket.h:67
EAccessMode
Definition: TSystem.h:54
void Reset()
Definition: TSystem.h:223
Bool_t ChangeDirectory(const char *path)
Change directory. Returns kTRUE in case of success, kFALSE otherwise.
const char * GetLinkedLibraries()
Get list of shared libraries loaded at the start of the executable.
char * GetServiceByPort(int port)
Get name of internet service.
Int_t fMemTotal
Definition: TSystem.h:191
int pw_gid
Definition: TWinNTSystem.h:53
int EscChar(const char *src, char *dst, int dstlen, char *specchars, char escchar)
Escape specchars in src with escchar and copy to dst.
Definition: TString.cxx:2549
virtual void HandleException(Int_t sig)
Handle exceptions (kSigBus, kSigSegmentationViolation, kSigIllegalInstruction and kSigFloatingExcepti...
typedef void((*Func_t)())
void ResetSignal(ESignals sig, Bool_t reset=kTRUE)
If reset is true reset the signal handler for the specified signal to the default handler...
void IgnoreSignal(ESignals sig, Bool_t ignore=kTRUE)
If ignore is true ignore the specified signal, else restore previous behaviour.
const Ssiz_t kNPOS
Definition: Rtypes.h:115
static const char * UnixGetdirentry(void *dir)
Returns the next directory entry.
virtual void AddTimer(TTimer *t)
Add timer to list of system timers.
Definition: TSystem.cxx:476
Definition: file.py:1
R__EXTERN const char * gRootDir
Definition: TSystem.h:233
void ResetTimer(TTimer *ti)
Reset a-sync timer.
void AddDynamicPath(const char *lib)
Add a new directory to the dynamic path.
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
ESignals GetSignal() const
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
const char * GetDirEntry(void *dirp)
Get next Unix file system directory entry. Returns 0 if no more entries.
int GetSysInfo(SysInfo_t *info) const
Returns static system info, like OS type, CPU type, number of CPUs RAM size, etc into the SysInfo_t s...
Int_t fMemUsed
Definition: TSystem.h:192
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
Int_t fCpuSpeed
Definition: TSystem.h:166
TInetAddress GetPeerName(int sock)
Get Internet Protocol (IP) address of remote host and port #.
void AddFileHandler(TFileHandler *fh)
Add a file handler to the list of system file handlers.
#define NULL
Definition: Rtypes.h:82
Long_t fIno
Definition: TSystem.h:137
#define snprintf
Definition: civetweb.c:822
FILE * TempFileName(TString &base, const char *dir=0)
Create a secure temporary file by appending a unique 6 letter string to base.
char * pw_passwd
Definition: TWinNTSystem.h:51
char * pw_dir
Definition: TWinNTSystem.h:56
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition: TSystem.cxx:831
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
Iterator of ordered collection.
TSignalHandler * RemoveSignalHandler(TSignalHandler *sh)
Remove a signal handler from list of signal handlers.
int AnnounceUnixService(int port, int backlog)
Announce unix domain service on path "kServerPath/<port>".
virtual Bool_t ReadNotify()
Notify when something can be read from the descriptor associated with this handler.
int ClosePipe(FILE *pipe)
Close the pipe.
void SetDynamicPath(const char *lib)
Set the dynamic path to a new value.
int Link(const char *from, const char *to)
Create a link from file1 to file2.
void Abort(int code=0)
Abort the application.
void Unload(const char *module)
Unload a shared library.
virtual void AddFileHandler(TFileHandler *fh)
Add a file handler to the list of system file handlers.
Definition: TSystem.cxx:559
void SigAlarmInterruptsSyscalls(Bool_t set)
When the argument is true the SIGALRM signal handler is set so that interrupted syscalls will not be ...
Int_t GetEffectiveGid()
Returns the effective group id.
double result[121]
Float_t fTotal
Definition: TSystem.h:182
Bool_t CheckSignals(Bool_t sync)
Check if some signals were raised and call their Notify() member.
static int UnixUdpConnect(const char *hostname, int port)
Creates a UDP socket connection Is called via the TSocket constructor.
int GetServiceByName(const char *service)
Get port # of internet service.
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1243
#define org(otri, vertexptr)
Definition: triangle.c:1037
TTime Now()
Get current time in milliseconds since 0:00 Jan 1 1995.
Int_t fSwapTotal
Definition: TSystem.h:194
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
void Openlog(const char *name, Int_t options, ELogFacility facility)
Open connection to system log daemon.
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:517
Long_t fDev
Definition: TSystem.h:136
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
virtual const char * GetSTLIncludePath() const
Definition: TInterpreter.h:137
UserGroup_t * GetUserInfo(Int_t uid)
Returns all user info in the UserGroup_t structure.
Abstract base class defining a generic interface to the underlying Operating System.
Definition: TSystem.h:258
const Bool_t kTRUE
Definition: Rtypes.h:91
float * q
Definition: THbookFile.cxx:87
Int_t fStdErrDup
Definition: TSystem.h:219
Ordered collection.
void DispatchSignals(ESignals sig)
Handle and dispatch signals.
int SendBuf(int sock, const void *buffer, int length)
Send a buffer headed by a length indicator.
void ListLibraries(const char *regexp="")
List all loaded shared libraries.
Float_t fIdle
Definition: TSystem.h:183
const char * WorkingDirectory()
Return working directory.
const Int_t n
Definition: legend1.C:16
TString fFile
Definition: TSystem.h:215
int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
char name[80]
Definition: TGX11.cxx:109
Long_t fMemResident
Definition: TSystem.h:206
const char * cnt
Definition: TXMLSetup.cxx:75
Bool_t IsAsync() const
Definition: TTimer.h:87
void Setenv(const char *name, const char *value)
Set environment variable.
int OpenConnection(const char *server, int port, int tcpwindowsize=-1, const char *protocol="tcp")
Open a connection to a service on a server.
virtual Bool_t HasReadInterest()
True if handler is interested in read events.
int AnnounceUdpService(int port, int backlog)
Announce UDP service.