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