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