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