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