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