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