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