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