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