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