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