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