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