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