Logo ROOT   6.16/01
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>
22#include "TUnixSystem.h"
23#include "TROOT.h"
24#include "TError.h"
25#include "TOrdCollection.h"
26#include "TRegexp.h"
27#include "TPRegexp.h"
28#include "TException.h"
29#include "Demangle.h"
30#include "TEnv.h"
31#include "TSocket.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 TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
504 // first loaded is the app so set ROOTSYS to app bundle
505 if (i == 1) {
506 char respath[kMAXPATHLEN];
507 if (!realpath(lib, respath)) {
508 if (!gSystem->Getenv("ROOTSYS"))
509 ::SysError("TUnixSystem::DylibAdded", "error getting realpath of %s", gSystem->BaseName(lib));
510 } else {
511 TString rs = gSystem->DirName(respath);
512 gSystem->Setenv("ROOTSYS", rs);
513 }
514 }
515#else
516 if (lib.EndsWith("libCore.dylib") || lib.EndsWith("libCore.so") ||
517 lib.Index(sovers) != kNPOS || lib.Index(dyvers) != kNPOS) {
518 char respath[kMAXPATHLEN];
519 if (!realpath(lib, respath)) {
520 if (!gSystem->Getenv("ROOTSYS"))
521 ::SysError("TUnixSystem::DylibAdded", "error getting realpath of libCore, please set ROOTSYS in the shell");
522 } else {
523 TString rs = gSystem->DirName(respath);
524 gSystem->Setenv("ROOTSYS", gSystem->DirName(rs));
525 }
526 }
527#endif
528#ifdef ROOTPREFIX
529 }
530#endif
531
532 // when libSystem.B.dylib is loaded we have finished loading all dylibs
533 // explicitly linked against the executable. Additional dylibs
534 // come when they are explicitly linked against loaded so's, currently
535 // we are not interested in these
536 if (lib.EndsWith("/libSystem.B.dylib"))
537 gotFirstSo = kTRUE;
538
539 // add all libs loaded before libSystem.B.dylib
540 if (!gotFirstSo && (lib.EndsWith(".dylib") || lib.EndsWith(".so"))) {
541 sovers = "\\.[0-9]+\\.*[0-9]*\\.so";
542 Ssiz_t idx = lib.Index(sovers);
543 if (idx != kNPOS) {
544 lib.Remove(idx);
545 lib += ".so";
546 }
547 dyvers = "\\.[0-9]+\\.*[0-9]*\\.dylib";
548 idx = lib.Index(dyvers);
549 if (idx != kNPOS) {
550 lib.Remove(idx);
551 lib += ".dylib";
552 }
554 if (linkedDylibs.Length())
555 linkedDylibs += " ";
556 linkedDylibs += lib;
557 }
558 }
559}
560#endif
561
563
564////////////////////////////////////////////////////////////////////////////////
565
566TUnixSystem::TUnixSystem() : TSystem("Unix", "Unix System")
567{ }
568
569////////////////////////////////////////////////////////////////////////////////
570/// Reset to original state.
571
573{
575
576 delete fReadmask;
577 delete fWritemask;
578 delete fReadready;
579 delete fWriteready;
580 delete fSignals;
581}
582
583////////////////////////////////////////////////////////////////////////////////
584/// Initialize Unix system interface.
585
587{
588 if (TSystem::Init())
589 return kTRUE;
590
591 fReadmask = new TFdSet;
592 fWritemask = new TFdSet;
593 fReadready = new TFdSet;
594 fWriteready = new TFdSet;
595 fSignals = new TFdSet;
596
597 //--- install default handlers
608
609#if defined(R__MACOSX)
610 // trap loading of all dylibs to register dylib name,
611 // sets also ROOTSYS if built without ROOTPREFIX
612 _dyld_register_func_for_add_image(DylibAdded);
613#elif defined(HAVE_DLADDR)
614 SetRootSys();
615#endif
616
617 // This is a fallback in case TROOT::GetRootSys() can't determine ROOTSYS
618 gRootDir = "/usr/local/root";
619
620 return kFALSE;
621}
622
623//---- Misc --------------------------------------------------------------------
624
625////////////////////////////////////////////////////////////////////////////////
626/// Set the application name (from command line, argv[0]) and copy it in
627/// gProgName. Copy the application pathname in gProgPath.
628/// If name is 0 let the system set the actual executable name and path
629/// (works on MacOS X and Linux).
630
632{
633 if (gProgName)
634 delete [] gProgName;
635 if (gProgPath)
636 delete [] gProgPath;
637
638 if (!name || !*name) {
639 name = GetExePath();
642 } else {
644 char *w = Which(Getenv("PATH"), gProgName);
646 delete [] w;
647 }
648}
649
650////////////////////////////////////////////////////////////////////////////////
651/// Set DISPLAY environment variable based on utmp entry. Only for UNIX.
652
654{
655 if (!Getenv("DISPLAY")) {
656 char *tty = ::ttyname(0); // device user is logged in on
657 if (tty) {
658 tty += 5; // remove "/dev/"
659
660 TUtmpContent utmp;
661 utmp.ReadUtmpFile();
662
663 STRUCT_UTMP *utmp_entry = utmp.SearchUtmpEntry(tty);
664 if (utmp_entry) {
665 if (utmp_entry->ut_host[0]) {
666 if (strchr(utmp_entry->ut_host, ':')) {
667 Setenv("DISPLAY", utmp_entry->ut_host);
668 Warning("SetDisplay", "DISPLAY not set, setting it to %s",
669 utmp_entry->ut_host);
670 } else {
671 char disp[260];
672 snprintf(disp, sizeof(disp), "%s:0.0", utmp_entry->ut_host);
673 Setenv("DISPLAY", disp);
674 Warning("SetDisplay", "DISPLAY not set, setting it to %s",
675 disp);
676 }
677 }
678#ifndef UTMP_NO_ADDR
679 else if (utmp_entry->ut_addr) {
680
681 struct sockaddr_in addr;
682 addr.sin_family = AF_INET;
683 addr.sin_port = 0;
684 memcpy(&addr.sin_addr, &utmp_entry->ut_addr, sizeof(addr.sin_addr));
685 memset(&addr.sin_zero[0], 0, sizeof(addr.sin_zero));
686 struct sockaddr *sa = (struct sockaddr *) &addr; // input
687
688 char hbuf[NI_MAXHOST + 4];
689 if (getnameinfo(sa, sizeof(struct sockaddr), hbuf, sizeof(hbuf), nullptr, 0, NI_NAMEREQD) == 0) {
690 assert( strlen(hbuf) < NI_MAXHOST );
691 strcat(hbuf, ":0.0");
692 Setenv("DISPLAY", hbuf);
693 Warning("SetDisplay", "DISPLAY not set, setting it to %s",
694 hbuf);
695 }
696 }
697#endif
698 }
699 }
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.
2148 if (gROOT) {
2149 gROOT->EndOfProcessCleanups();
2150 } else if (gInterpreter) {
2151 gInterpreter->ResetGlobals();
2152 }
2153
2154 if (mode)
2155 ::exit(code);
2156 else
2157 ::_exit(code);
2158}
2159
2160////////////////////////////////////////////////////////////////////////////////
2161/// Abort the application.
2162
2164{
2165 ::abort();
2166}
2167
2168
2169#ifdef R__MACOSX
2170/// Use CoreSymbolication to retrieve the stacktrace.
2171#include <mach/mach.h>
2172extern "C" {
2173 // Adapted from https://github.com/mountainstorm/CoreSymbolication
2174 // Under the hood the framework basically just calls through to a set of C++ libraries
2175 typedef struct {
2176 void* csCppData;
2177 void* csCppObj;
2178 } CSTypeRef;
2179 typedef CSTypeRef CSSymbolicatorRef;
2180 typedef CSTypeRef CSSourceInfoRef;
2181 typedef CSTypeRef CSSymbolOwnerRef;
2182 typedef CSTypeRef CSSymbolRef;
2183
2184 CSSymbolicatorRef CSSymbolicatorCreateWithPid(pid_t pid);
2185 CSSymbolRef CSSymbolicatorGetSymbolWithAddressAtTime(CSSymbolicatorRef cs, vm_address_t addr, uint64_t time);
2186 CSSourceInfoRef CSSymbolicatorGetSourceInfoWithAddressAtTime(CSSymbolicatorRef cs, vm_address_t addr, uint64_t time);
2187 const char* CSSymbolGetName(CSSymbolRef sym);
2188 CSSymbolOwnerRef CSSymbolGetSymbolOwner(CSSymbolRef sym);
2189 const char* CSSymbolOwnerGetPath(CSSymbolOwnerRef symbol);
2190 const char* CSSourceInfoGetPath(CSSourceInfoRef info);
2191 int CSSourceInfoGetLineNumber(CSSourceInfoRef info);
2192}
2193
2194bool CSTypeRefIdValid(CSTypeRef ref) {
2195 return ref.csCppData || ref.csCppObj;
2196}
2197
2198void macosx_backtrace() {
2199void* addrlist[kMAX_BACKTRACE_DEPTH];
2200 // retrieve current stack addresses
2201 int numstacks = backtrace( addrlist, sizeof( addrlist ) / sizeof( void* ));
2202
2203 CSSymbolicatorRef symbolicator = CSSymbolicatorCreateWithPid(getpid());
2204
2205 // skip TUnixSystem::Backtrace(), macosx_backtrace()
2206 static const int skipFrames = 2;
2207 for (int i = skipFrames; i < numstacks; ++i) {
2208 // No debug info, try to get at least the symbol name.
2209 CSSymbolRef sym = CSSymbolicatorGetSymbolWithAddressAtTime(symbolicator,
2210 (vm_address_t)addrlist[i],
2211 0x80000000u);
2212 CSSymbolOwnerRef symOwner = CSSymbolGetSymbolOwner(sym);
2213
2214 if (const char* libPath = CSSymbolOwnerGetPath(symOwner)) {
2215 printf("[%s]", libPath);
2216 } else {
2217 printf("[<unknown binary>]");
2218 }
2219
2220 if (const char* symname = CSSymbolGetName(sym)) {
2221 printf(" %s", symname);
2222 }
2223
2224 CSSourceInfoRef sourceInfo
2225 = CSSymbolicatorGetSourceInfoWithAddressAtTime(symbolicator,
2226 (vm_address_t)addrlist[i],
2227 0x80000000u /*"now"*/);
2228 if (const char* sourcePath = CSSourceInfoGetPath(sourceInfo)) {
2229 printf(" %s:%d", sourcePath, (int)CSSourceInfoGetLineNumber(sourceInfo));
2230 } else {
2231 printf(" (no debug info)");
2232 }
2233 printf("\n");
2234 }
2235}
2236#endif // R__MACOSX
2237
2238////////////////////////////////////////////////////////////////////////////////
2239/// Print a stack trace.
2240
2242{
2243 if (!gEnv->GetValue("Root.Stacktrace", 1))
2244 return;
2245
2246#ifndef R__MACOSX
2247 TString gdbscript = gEnv->GetValue("Root.StacktraceScript", "");
2248 gdbscript = gdbscript.Strip();
2249 if (gdbscript != "") {
2250 if (AccessPathName(gdbscript, kReadPermission)) {
2251 fprintf(stderr, "Root.StacktraceScript %s does not exist\n", gdbscript.Data());
2252 gdbscript = "";
2253 }
2254 }
2255 if (gdbscript == "") {
2256 gdbscript = "gdb-backtrace.sh";
2258 if (AccessPathName(gdbscript, kReadPermission)) {
2259 fprintf(stderr, "Error in <TUnixSystem::StackTrace> script %s is missing\n", gdbscript.Data());
2260 return;
2261 }
2262 }
2263 gdbscript += " ";
2264
2265 TString gdbmess = gEnv->GetValue("Root.StacktraceMessage", "");
2266 gdbmess = gdbmess.Strip();
2267
2268 std::cout.flush();
2269 fflush(stdout);
2270
2271 std::cerr.flush();
2272 fflush(stderr);
2273
2274 int fd = STDERR_FILENO;
2275
2276 const char *message = " Generating stack trace...\n";
2277
2278 if (fd && message) { } // remove unused warning (remove later)
2279
2280 if (gApplication && !strcmp(gApplication->GetName(), "TRint"))
2281 Getlinem(kCleanUp, 0);
2282
2283#if defined(USE_GDB_STACK_TRACE)
2284 char *gdb = Which(Getenv("PATH"), "gdb", kExecutePermission);
2285 if (!gdb) {
2286 fprintf(stderr, "gdb not found, need it for stack trace\n");
2287 return;
2288 }
2289
2290 // write custom message file
2291 TString gdbmessf = "gdb-message";
2292 if (gdbmess != "") {
2293 FILE *f = TempFileName(gdbmessf);
2294 fprintf(f, "%s\n", gdbmess.Data());
2295 fclose(f);
2296 }
2297
2298 // use gdb to get stack trace
2299 gdbscript += GetExePath();
2300 gdbscript += " ";
2301 gdbscript += GetPid();
2302 if (gdbmess != "") {
2303 gdbscript += " ";
2304 gdbscript += gdbmessf;
2305 }
2306 gdbscript += " 1>&2";
2307 Exec(gdbscript);
2308 delete [] gdb;
2309 return;
2310
2311#elif defined(R__AIX)
2312 TString script = "procstack ";
2313 script += GetPid();
2314 Exec(script);
2315 return;
2316#elif defined(R__SOLARIS)
2317 char *cppfilt = Which(Getenv("PATH"), "c++filt", kExecutePermission);
2318 TString script = "pstack ";
2319 script += GetPid();
2320 if (cppfilt) {
2321 script += " | ";
2322 script += cppfilt;
2323 delete [] cppfilt;
2324 }
2325 Exec(script);
2326 return;
2327#elif defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_DLADDR) // linux + MacOS X >= 10.5
2328 // we could have used backtrace_symbols_fd, except its output
2329 // format is pretty bad, so recode that here :-(
2330
2331 // take care of demangling
2333
2334 // check for c++filt
2335 const char *cppfilt = "c++filt";
2336 const char *cppfiltarg = "";
2337#ifdef R__B64
2338 const char *format1 = " 0x%016lx in %.200s %s 0x%lx from %.200s\n";
2339#ifdef R__MACOSX
2340 const char *format2 = " 0x%016lx in %.200s\n";
2341#else
2342 const char *format2 = " 0x%016lx in %.200s at %.200s from %.200s\n";
2343#endif
2344 const char *format3 = " 0x%016lx in %.200s from %.200s\n";
2345 const char *format4 = " 0x%016lx in <unknown function>\n";
2346#else
2347 const char *format1 = " 0x%08lx in %.200s %s 0x%lx from %.200s\n";
2348#ifdef R__MACOSX
2349 const char *format2 = " 0x%08lx in %.200s\n";
2350#else
2351 const char *format2 = " 0x%08lx in %.200s at %.200s from %.200s\n";
2352#endif
2353 const char *format3 = " 0x%08lx in %.200s from %.200s\n";
2354 const char *format4 = " 0x%08lx in <unknown function>\n";
2355#endif
2356
2357 char *filter = Which(Getenv("PATH"), cppfilt, kExecutePermission);
2358 if (!filter)
2359 demangle = kFALSE;
2360
2361#if (__GNUC__ >= 3)
2362 // try finding supported format option for g++ v3
2363 if (filter) {
2364 FILE *p = OpenPipe(TString::Format("%s --help 2>&1", filter), "r");
2365 TString help;
2366 while (help.Gets(p)) {
2367 if (help.Index("gnu-v3") != kNPOS) {
2368 cppfiltarg = "--format=gnu-v3";
2369 break;
2370 } else if (help.Index("gnu-new-abi") != kNPOS) {
2371 cppfiltarg = "--format=gnu-new-abi";
2372 break;
2373 }
2374 }
2375 ClosePipe(p);
2376 }
2377#endif
2378 // gdb-backtrace.sh uses gdb to produce a backtrace. See if it is available.
2379 // If it is, use it. If not proceed as before.
2380#if (defined(R__LINUX) && !defined(R__WINGCC))
2381 // Declare the process that will be generating the stacktrace
2382 // For more see: http://askubuntu.com/questions/41629/after-upgrade-gdb-wont-attach-to-process
2383#ifdef PR_SET_PTRACER
2384 prctl(PR_SET_PTRACER, getpid(), 0, 0, 0);
2385#endif
2386#endif
2387 char *gdb = Which(Getenv("PATH"), "gdb", kExecutePermission);
2388 if (gdb) {
2389 // write custom message file
2390 TString gdbmessf = "gdb-message";
2391 if (gdbmess != "") {
2392 FILE *f = TempFileName(gdbmessf);
2393 fprintf(f, "%s\n", gdbmess.Data());
2394 fclose(f);
2395 }
2396
2397 // use gdb to get stack trace
2398#ifdef R__MACOSX
2399 gdbscript += GetExePath();
2400 gdbscript += " ";
2401#endif
2402 gdbscript += GetPid();
2403 if (gdbmess != "") {
2404 gdbscript += " ";
2405 gdbscript += gdbmessf;
2406 }
2407 gdbscript += " 1>&2";
2408 Exec(gdbscript);
2409 delete [] gdb;
2410 } else {
2411 // addr2line uses debug info to convert addresses into file names
2412 // and line numbers
2413#ifdef R__MACOSX
2414 char *addr2line = Which(Getenv("PATH"), "atos", kExecutePermission);
2415#else
2416 char *addr2line = Which(Getenv("PATH"), "addr2line", kExecutePermission);
2417#endif
2418 if (addr2line) {
2419 // might take some time so tell what we are doing...
2420 if (write(fd, message, strlen(message)) < 0)
2421 Warning("StackTrace", "problems writing line numbers (errno: %d)", TSystem::GetErrno());
2422 }
2423
2424 // open tmp file for demangled stack trace
2425 TString tmpf1 = "gdb-backtrace";
2426 std::ofstream file1;
2427 if (demangle) {
2428 FILE *f = TempFileName(tmpf1);
2429 if (f) fclose(f);
2430 file1.open(tmpf1);
2431 if (!file1) {
2432 Error("StackTrace", "could not open file %s", tmpf1.Data());
2433 Unlink(tmpf1);
2434 demangle = kFALSE;
2435 }
2436 }
2437
2438#ifdef R__MACOSX
2439 if (addr2line)
2440 demangle = kFALSE; // atos always demangles
2441#endif
2442
2443 char buffer[4096];
2444 void *trace[kMAX_BACKTRACE_DEPTH];
2445 int depth = backtrace(trace, kMAX_BACKTRACE_DEPTH);
2446 for (int n = 5; n < depth; n++) {
2447 ULong_t addr = (ULong_t) trace[n];
2448 Dl_info info;
2449
2450 if (dladdr(trace[n], &info) && info.dli_fname && info.dli_fname[0]) {
2451 const char *libname = info.dli_fname;
2452 const char *symname = (info.dli_sname && info.dli_sname[0]) ?
2453 info.dli_sname : "<unknown>";
2454 ULong_t libaddr = (ULong_t) info.dli_fbase;
2455 ULong_t symaddr = (ULong_t) info.dli_saddr;
2456 Bool_t gte = (addr >= symaddr);
2457 ULong_t diff = (gte) ? addr - symaddr : symaddr - addr;
2458 if (addr2line && symaddr) {
2459 Bool_t nodebug = kTRUE;
2460#ifdef R__MACOSX
2461 if (libaddr) { } // use libaddr
2462#if defined(MAC_OS_X_VERSION_10_10)
2463 snprintf(buffer, sizeof(buffer), "%s -p %d 0x%016lx", addr2line, GetPid(), addr);
2464#elif defined(MAC_OS_X_VERSION_10_9)
2465 // suppress deprecation warning with opti
2466 snprintf(buffer, sizeof(buffer), "%s -d -p %d 0x%016lx", addr2line, GetPid(), addr);
2467#else
2468 snprintf(buffer, sizeof(buffer), "%s -p %d 0x%016lx", addr2line, GetPid(), addr);
2469#endif
2470#else
2471 ULong_t offset = (addr >= libaddr) ? addr - libaddr :
2472 libaddr - addr;
2473 TString name = TString(libname);
2474 Bool_t noPath = kFALSE;
2475 Bool_t noShare = kTRUE;
2476 if (name[0] != '/') noPath = kTRUE;
2477 if (name.Contains(".so") || name.Contains(".sl")) noShare = kFALSE;
2478 if (noShare) offset = addr;
2479 if (noPath) name = "`which " + name + "`";
2480 snprintf(buffer, sizeof(buffer), "%s -e %s 0x%016lx", addr2line, name.Data(), offset);
2481#endif
2482 if (FILE *pf = ::popen(buffer, "r")) {
2483 char buf[2048];
2484 if (fgets(buf, 2048, pf)) {
2485 buf[strlen(buf)-1] = 0; // remove trailing \n
2486 if (strncmp(buf, "??", 2)) {
2487#ifdef R__MACOSX
2488 snprintf(buffer, sizeof(buffer), format2, addr, buf);
2489#else
2490 snprintf(buffer, sizeof(buffer), format2, addr, symname, buf, libname);
2491#endif
2492 nodebug = kFALSE;
2493 }
2494 }
2495 ::pclose(pf);
2496 }
2497 if (nodebug)
2498 snprintf(buffer, sizeof(buffer), format1, addr, symname,
2499 gte ? "+" : "-", diff, libname);
2500 } else {
2501 if (symaddr)
2502 snprintf(buffer, sizeof(buffer), format1, addr, symname,
2503 gte ? "+" : "-", diff, libname);
2504 else
2505 snprintf(buffer, sizeof(buffer), format3, addr, symname, libname);
2506 }
2507 } else {
2508 snprintf(buffer, sizeof(buffer), format4, addr);
2509 }
2510
2511 if (demangle)
2512 file1 << buffer;
2513 else
2514 if (write(fd, buffer, ::strlen(buffer)) < 0)
2515 Warning("StackTrace", "problems writing buffer (errno: %d)", TSystem::GetErrno());
2516 }
2517
2518 if (demangle) {
2519 TString tmpf2 = "gdb-backtrace";
2520 FILE *f = TempFileName(tmpf2);
2521 if (f) fclose(f);
2522 file1.close();
2523 snprintf(buffer, sizeof(buffer), "%s %s < %s > %s", filter, cppfiltarg, tmpf1.Data(), tmpf2.Data());
2524 Exec(buffer);
2525 std::ifstream file2(tmpf2);
2526 TString line;
2527 while (file2) {
2528 line = "";
2529 line.ReadString(file2);
2530 if (write(fd, line.Data(), line.Length()) < 0)
2531 Warning("StackTrace", "problems writing line (errno: %d)", TSystem::GetErrno());
2532 }
2533 file2.close();
2534 Unlink(tmpf1);
2535 Unlink(tmpf2);
2536 }
2537
2538 delete [] addr2line;
2539 }
2540 delete [] filter;
2541#elif defined(HAVE_EXCPT_H) && defined(HAVE_PDSC_H) && \
2542 defined(HAVE_RLD_INTERFACE_H) // tru64
2543 // Tru64 stack walk. Uses the exception handling library and the
2544 // run-time linker's core functions (loader(5)). FIXME: Tru64
2545 // should have _RLD_DLADDR like IRIX below. Verify and update.
2546
2547 char buffer [128];
2548 sigcontext context;
2549 int rc = 0;
2550
2551 exc_capture_context (&context);
2552 while (!rc && context.sc_pc) {
2553 // FIXME: Elf32?
2554 pdsc_crd *func, *base, *crd
2555 = exc_remote_lookup_function_entry(0, 0, context.sc_pc, 0, &func, &base);
2556 Elf32_Addr addr = PDSC_CRD_BEGIN_ADDRESS(base, func);
2557 // const char *name = _rld_address_to_name(addr);
2558 const char *name = "<unknown function>";
2559 sprintf(buffer, " 0x%012lx %.200s + 0x%lx\n",
2560 context.sc_pc, name, context.sc_pc - addr);
2561 write(fd, buffer, ::strlen(buffer));
2562 rc = exc_virtual_unwind(0, &context);
2563 }
2564#endif
2565#else //R__MACOSX
2566 macosx_backtrace();
2567#endif //R__MACOSX
2568}
2569
2570//---- System Logging ----------------------------------------------------------
2571
2572////////////////////////////////////////////////////////////////////////////////
2573/// Open connection to system log daemon. For the use of the options and
2574/// facility see the Unix openlog man page.
2575
2576void TUnixSystem::Openlog(const char *name, Int_t options, ELogFacility facility)
2577{
2578 int fac = 0;
2579
2580 switch (facility) {
2581 case kLogLocal0:
2582 fac = LOG_LOCAL0;
2583 break;
2584 case kLogLocal1:
2585 fac = LOG_LOCAL1;
2586 break;
2587 case kLogLocal2:
2588 fac = LOG_LOCAL2;
2589 break;
2590 case kLogLocal3:
2591 fac = LOG_LOCAL3;
2592 break;
2593 case kLogLocal4:
2594 fac = LOG_LOCAL4;
2595 break;
2596 case kLogLocal5:
2597 fac = LOG_LOCAL5;
2598 break;
2599 case kLogLocal6:
2600 fac = LOG_LOCAL6;
2601 break;
2602 case kLogLocal7:
2603 fac = LOG_LOCAL7;
2604 break;
2605 }
2606
2607 ::openlog(name, options, fac);
2608}
2609
2610////////////////////////////////////////////////////////////////////////////////
2611/// Send mess to syslog daemon. Level is the logging level and mess the
2612/// message that will be written on the log.
2613
2614void TUnixSystem::Syslog(ELogLevel level, const char *mess)
2615{
2616 // ELogLevel matches exactly the Unix values.
2617 ::syslog(level, "%s", mess);
2618}
2619
2620////////////////////////////////////////////////////////////////////////////////
2621/// Close connection to system log daemon.
2622
2624{
2625 ::closelog();
2626}
2627
2628//---- Standard output redirection ---------------------------------------------
2629
2630////////////////////////////////////////////////////////////////////////////////
2631/// Redirect standard output (stdout, stderr) to the specified file.
2632/// If the file argument is 0 the output is set again to stderr, stdout.
2633/// The second argument specifies whether the output should be added to the
2634/// file ("a", default) or the file be truncated before ("w").
2635/// This function saves internally the current state into a static structure.
2636/// The call can be made reentrant by specifying the opaque structure pointed
2637/// by 'h', which is filled with the relevant information. The handle 'h'
2638/// obtained on the first call must then be used in any subsequent call,
2639/// included ShowOutput, to display the redirected output.
2640/// Returns 0 on success, -1 in case of error.
2641
2642Int_t TUnixSystem::RedirectOutput(const char *file, const char *mode,
2644{
2645 // Instance to be used if the caller does not passes 'h'
2646 static RedirectHandle_t loch;
2647
2648 Int_t rc = 0;
2649
2650 // Which handle to use ?
2651 RedirectHandle_t *xh = (h) ? h : &loch;
2652
2653 if (file) {
2654 // Save the paths
2655 Bool_t outdone = kFALSE;
2656 if (xh->fStdOutTty.IsNull()) {
2657 const char *tty = ttyname(STDOUT_FILENO);
2658 if (tty) {
2659 xh->fStdOutTty = tty;
2660 } else {
2661 if ((xh->fStdOutDup = dup(STDOUT_FILENO)) < 0) {
2662 SysError("RedirectOutput", "could not 'dup' stdout (errno: %d)", TSystem::GetErrno());
2663 return -1;
2664 }
2665 outdone = kTRUE;
2666 }
2667 }
2668 if (xh->fStdErrTty.IsNull()) {
2669 const char *tty = ttyname(STDERR_FILENO);
2670 if (tty) {
2671 xh->fStdErrTty = tty;
2672 } else {
2673 if ((xh->fStdErrDup = dup(STDERR_FILENO)) < 0) {
2674 SysError("RedirectOutput", "could not 'dup' stderr (errno: %d)", TSystem::GetErrno());
2675 if (outdone && dup2(xh->fStdOutDup, STDOUT_FILENO) < 0) {
2676 Warning("RedirectOutput", "could not restore stdout (back to original redirected"
2677 " file) (errno: %d)", TSystem::GetErrno());
2678 }
2679 return -1;
2680 }
2681 }
2682 }
2683
2684 // Make sure mode makes sense; default "a"
2685 const char *m = (mode[0] == 'a' || mode[0] == 'w') ? mode : "a";
2686
2687 // Current file size
2688 xh->fReadOffSet = 0;
2689 if (m[0] == 'a') {
2690 // If the file exists, save the current size
2691 FileStat_t st;
2692 if (!gSystem->GetPathInfo(file, st))
2693 xh->fReadOffSet = (st.fSize > 0) ? st.fSize : xh->fReadOffSet;
2694 }
2695 xh->fFile = file;
2696
2697 // Redirect stdout & stderr
2698 if (freopen(file, m, stdout) == 0) {
2699 SysError("RedirectOutput", "could not freopen stdout (errno: %d)", TSystem::GetErrno());
2700 return -1;
2701 }
2702 if (freopen(file, m, stderr) == 0) {
2703 SysError("RedirectOutput", "could not freopen stderr (errno: %d)", TSystem::GetErrno());
2704 if (freopen(xh->fStdOutTty.Data(), "a", stdout) == 0)
2705 SysError("RedirectOutput", "could not restore stdout (errno: %d)", TSystem::GetErrno());
2706 return -1;
2707 }
2708 } else {
2709 // Restore stdout & stderr
2710 fflush(stdout);
2711 if (!(xh->fStdOutTty.IsNull())) {
2712 if (freopen(xh->fStdOutTty.Data(), "a", stdout) == 0) {
2713 SysError("RedirectOutput", "could not restore stdout (errno: %d)", TSystem::GetErrno());
2714 rc = -1;
2715 }
2716 xh->fStdOutTty = "";
2717 } else {
2718 if (close(STDOUT_FILENO) != 0) {
2719 SysError("RedirectOutput",
2720 "problems closing STDOUT_FILENO (%d) before 'dup2' (errno: %d)",
2721 STDOUT_FILENO, TSystem::GetErrno());
2722 rc = -1;
2723 }
2724 if (dup2(xh->fStdOutDup, STDOUT_FILENO) < 0) {
2725 SysError("RedirectOutput", "could not restore stdout (back to original redirected"
2726 " file) (errno: %d)", TSystem::GetErrno());
2727 rc = -1;
2728 }
2729 if (close(xh->fStdOutDup) != 0) {
2730 SysError("RedirectOutput",
2731 "problems closing temporary 'out' descriptor %d (errno: %d)",
2733 rc = -1;
2734 }
2735 }
2736 fflush(stderr);
2737 if (!(xh->fStdErrTty.IsNull())) {
2738 if (freopen(xh->fStdErrTty.Data(), "a", stderr) == 0) {
2739 SysError("RedirectOutput", "could not restore stderr (errno: %d)", TSystem::GetErrno());
2740 rc = -1;
2741 }
2742 xh->fStdErrTty = "";
2743 } else {
2744 if (close(STDERR_FILENO) != 0) {
2745 SysError("RedirectOutput",
2746 "problems closing STDERR_FILENO (%d) before 'dup2' (errno: %d)",
2747 STDERR_FILENO, TSystem::GetErrno());
2748 rc = -1;
2749 }
2750 if (dup2(xh->fStdErrDup, STDERR_FILENO) < 0) {
2751 SysError("RedirectOutput", "could not restore stderr (back to original redirected"
2752 " file) (errno: %d)", TSystem::GetErrno());
2753 rc = -1;
2754 }
2755 if (close(xh->fStdErrDup) != 0) {
2756 SysError("RedirectOutput",
2757 "problems closing temporary 'err' descriptor %d (errno: %d)",
2759 rc = -1;
2760 }
2761 }
2762 // Reset the static instance, if using that
2763 if (xh == &loch)
2764 xh->Reset();
2765 }
2766 return rc;
2767}
2768
2769//---- dynamic loading and linking ---------------------------------------------
2770
2771////////////////////////////////////////////////////////////////////////////////
2772///dynamic linking of module
2773
2774Func_t TUnixSystem::DynFindSymbol(const char * /*module*/, const char *entry)
2775{
2776 return TSystem::DynFindSymbol("*", entry);
2777}
2778
2779////////////////////////////////////////////////////////////////////////////////
2780/// Load a shared library. Returns 0 on successful loading, 1 in
2781/// case lib was already loaded and -1 in case lib does not exist
2782/// or in case of error.
2783
2784int TUnixSystem::Load(const char *module, const char *entry, Bool_t system)
2785{
2786 return TSystem::Load(module, entry, system);
2787}
2788
2789////////////////////////////////////////////////////////////////////////////////
2790/// Unload a shared library.
2791
2792void TUnixSystem::Unload(const char *module)
2793{
2794 if (module) { TSystem::Unload(module); }
2795}
2796
2797////////////////////////////////////////////////////////////////////////////////
2798/// List symbols in a shared library.
2799
2800void TUnixSystem::ListSymbols(const char * /*module*/, const char * /*regexp*/)
2801{
2802 Error("ListSymbols", "not yet implemented");
2803}
2804
2805////////////////////////////////////////////////////////////////////////////////
2806/// List all loaded shared libraries.
2807
2808void TUnixSystem::ListLibraries(const char *regexp)
2809{
2810 TSystem::ListLibraries(regexp);
2811}
2812
2813////////////////////////////////////////////////////////////////////////////////
2814/// Get list of shared libraries loaded at the start of the executable.
2815/// Returns 0 in case list cannot be obtained or in case of error.
2816
2818{
2819 static TString linkedLibs;
2820 static Bool_t once = kFALSE;
2821
2823
2824 if (!linkedLibs.IsNull())
2825 return linkedLibs;
2826
2827 if (once)
2828 return 0;
2829
2830#if !defined(R__MACOSX)
2831 const char *exe = GetExePath();
2832 if (!exe || !*exe)
2833 return 0;
2834#endif
2835
2836#if defined(R__MACOSX)
2837 DylibAdded(0, 0);
2838 linkedLibs = gLinkedDylibs;
2839#if 0
2840 FILE *p = OpenPipe(TString::Format("otool -L %s", exe), "r");
2841 TString otool;
2842 while (otool.Gets(p)) {
2843 TString delim(" \t");
2844 TObjArray *tok = otool.Tokenize(delim);
2845 TString dylib = ((TObjString*)tok->At(0))->String();
2846 if (dylib.EndsWith(".dylib") && !dylib.Contains("/libSystem.B.dylib")) {
2847 if (!linkedLibs.IsNull())
2848 linkedLibs += " ";
2849 linkedLibs += dylib;
2850 }
2851 delete tok;
2852 }
2853 if (p) {
2854 ClosePipe(p);
2855 }
2856#endif
2857#elif defined(R__LINUX) || defined(R__SOLARIS) || defined(R__AIX)
2858#if defined(R__WINGCC )
2859 const char *cLDD="cygcheck";
2860 const char *cSOEXT=".dll";
2861 size_t lenexe = strlen(exe);
2862 if (strcmp(exe + lenexe - 4, ".exe")
2863 && strcmp(exe + lenexe - 4, ".dll")) {
2864 // it's not a dll and exe doesn't end on ".exe";
2865 // need to add it for cygcheck to find it:
2866 char* longerexe = new char[lenexe + 5];
2867 strlcpy(longerexe, exe,lenexe+5);
2868 strlcat(longerexe, ".exe",lenexe+5);
2869 delete [] exe;
2870 exe = longerexe;
2871 }
2872 TRegexp sovers = "\\.so\\.[0-9]+";
2873#else
2874 const char *cLDD="ldd";
2875#if defined(R__AIX)
2876 const char *cSOEXT=".a";
2877 TRegexp sovers = "\\.a\\.[0-9]+";
2878#else
2879 const char *cSOEXT=".so";
2880 TRegexp sovers = "\\.so\\.[0-9]+";
2881#endif
2882#endif
2883 FILE *p = OpenPipe(TString::Format("%s '%s'", cLDD, exe), "r");
2884 if (p) {
2885 TString ldd;
2886 while (ldd.Gets(p)) {
2887 TString delim(" \t");
2888 TObjArray *tok = ldd.Tokenize(delim);
2889
2890 // expected format:
2891 // libCore.so => /home/rdm/root/lib/libCore.so (0x40017000)
2892 TObjString *solibName = (TObjString*)tok->At(2);
2893 if (!solibName) {
2894 // case where there is only one name of the list:
2895 // /usr/platform/SUNW,UltraAX-i2/lib/libc_psr.so.1
2896 solibName = (TObjString*)tok->At(0);
2897 }
2898 if (solibName) {
2899 TString solib = solibName->String();
2900 Ssiz_t idx = solib.Index(sovers);
2901 if (solib.EndsWith(cSOEXT) || idx != kNPOS) {
2902 if (idx != kNPOS)
2903 solib.Remove(idx+3);
2904 if (!AccessPathName(solib, kReadPermission)) {
2905 if (!linkedLibs.IsNull())
2906 linkedLibs += " ";
2907 linkedLibs += solib;
2908 }
2909 }
2910 }
2911 delete tok;
2912 }
2913 ClosePipe(p);
2914 }
2915#endif
2916
2917 once = kTRUE;
2918
2919 if (linkedLibs.IsNull())
2920 return 0;
2921
2922 return linkedLibs;
2923}
2924
2925//---- Time & Date -------------------------------------------------------------
2926
2927////////////////////////////////////////////////////////////////////////////////
2928/// Get current time in milliseconds since 0:00 Jan 1 1995.
2929
2931{
2932 return UnixNow();
2933}
2934
2935////////////////////////////////////////////////////////////////////////////////
2936/// Handle and dispatch timers. If mode = kTRUE dispatch synchronous
2937/// timers else a-synchronous timers.
2938
2940{
2941 if (!fTimers) return kFALSE;
2942
2944
2946 TTimer *t;
2947 Bool_t timedout = kFALSE;
2948
2949 while ((t = (TTimer *) it.Next())) {
2950 // NB: the timer resolution is added in TTimer::CheckTimer()
2951 Long64_t now = UnixNow();
2952 if (mode && t->IsSync()) {
2953 if (t->CheckTimer(now))
2954 timedout = kTRUE;
2955 } else if (!mode && t->IsAsync()) {
2956 if (t->CheckTimer(now)) {
2958 timedout = kTRUE;
2959 }
2960 }
2961 }
2963 return timedout;
2964}
2965
2966////////////////////////////////////////////////////////////////////////////////
2967/// Add timer to list of system timers.
2968
2970{
2972 ResetTimer(ti);
2973}
2974
2975////////////////////////////////////////////////////////////////////////////////
2976/// Remove timer from list of system timers.
2977
2979{
2980 if (!ti) return 0;
2981
2983
2985 if (ti->IsAsync())
2987 return t;
2988}
2989
2990////////////////////////////////////////////////////////////////////////////////
2991/// Reset a-sync timer.
2992
2994{
2995 if (!fInsideNotify && ti && ti->IsAsync())
2997}
2998
2999//---- RPC ---------------------------------------------------------------------
3000
3001////////////////////////////////////////////////////////////////////////////////
3002/// Get Internet Protocol (IP) address of host. Returns an TInetAddress
3003/// object. To see if the hostname lookup was successfull call
3004/// TInetAddress::IsValid().
3005
3007{
3008 TInetAddress ia;
3009 struct addrinfo hints;
3010 struct addrinfo *result, *rp;
3011 memset(&hints, 0, sizeof(struct addrinfo));
3012 hints.ai_family = AF_INET; // only IPv4
3013 hints.ai_socktype = 0; // any socket type
3014 hints.ai_protocol = 0; // any protocol
3015 hints.ai_flags = AI_CANONNAME; // get canonical name
3016#ifdef R__MACOSX
3017 // Anything ending on ".local" causes a 5 second delay in getaddrinfo().
3018 // See e.g. https://apple.stackexchange.com/questions/175320/why-is-my-hostname-resolution-taking-so-long
3019 // Only reasonable solution: remove the "domain" part if it's ".local".
3020 size_t lenHostname = strlen(hostname);
3021 std::string hostnameWithoutLocal{hostname};
3022 if (lenHostname > 6 && !strcmp(hostname + lenHostname - 6, ".local")) {
3023 hostnameWithoutLocal.erase(lenHostname - 6);
3024 hostname = hostnameWithoutLocal.c_str();
3025 }
3026#endif
3027
3028 // obsolete gethostbyname() replaced by getaddrinfo()
3029 int rc = getaddrinfo(hostname, nullptr, &hints, &result);
3030 if (rc != 0) {
3031 if (rc == EAI_NONAME) {
3032 if (gDebug > 0) Error("GetHostByName", "unknown host '%s'", hostname);
3033 ia.fHostname = "UnNamedHost";
3034 } else {
3035 Error("GetHostByName", "getaddrinfo failed for '%s': %s", hostname, gai_strerror(rc));
3036 ia.fHostname = "UnknownHost";
3037 }
3038 return ia;
3039 }
3040
3041 std::string hostcanon(result->ai_canonname ? result->ai_canonname : hostname);
3042 ia.fHostname = hostcanon.data();
3043 ia.fFamily = result->ai_family;
3044 ia.fAddresses[0] = ntohl(((struct sockaddr_in *)(result->ai_addr))->sin_addr.s_addr);
3045 // with getaddrinfo() no way to get list of aliases for a hostname
3046 if (hostcanon.compare(hostname) != 0) ia.AddAlias(hostname);
3047
3048 // check on numeric hostname
3049 char tmp[sizeof(struct in_addr)];
3050 if (inet_pton(AF_INET, hostcanon.data(), tmp) == 1) {
3051 char hbuf[NI_MAXHOST];
3052 if (getnameinfo(result->ai_addr, result->ai_addrlen, hbuf, sizeof(hbuf), nullptr, 0, 0) == 0)
3053 ia.fHostname = hbuf;
3054 }
3055
3056 // check other addresses (if exist)
3057 rp = result->ai_next;
3058 for (; rp != nullptr; rp = rp->ai_next) {
3059 UInt_t arp = ntohl(((struct sockaddr_in *)(rp->ai_addr))->sin_addr.s_addr);
3060 if ( !(std::find(ia.fAddresses.begin(), ia.fAddresses.end(), arp) != ia.fAddresses.end()) )
3061 ia.AddAddress(arp);
3062 }
3063
3064 freeaddrinfo(result);
3065 return ia;
3066}
3067
3068////////////////////////////////////////////////////////////////////////////////
3069/// Get Internet Protocol (IP) address of host and port #.
3070
3072{
3073 struct sockaddr addr;
3074#if defined(USE_SIZE_T)
3075 size_t len = sizeof(addr);
3076#elif defined(USE_SOCKLEN_T)
3077 socklen_t len = sizeof(addr);
3078#else
3079 int len = sizeof(addr);
3080#endif
3081
3082 TInetAddress ia;
3083 if (getsockname(sock, &addr, &len) == -1) {
3084 SysError("GetSockName", "getsockname failed");
3085 return ia;
3086 }
3087
3088 if (addr.sa_family != AF_INET) return ia; // only IPv4
3089 ia.fFamily = addr.sa_family;
3090 struct sockaddr_in *addrin = (struct sockaddr_in *)&addr;
3091 ia.fPort = ntohs(addrin->sin_port);
3092 ia.fAddresses[0] = ntohl(addrin->sin_addr.s_addr);
3093
3094 char hbuf[NI_MAXHOST];
3095 if (getnameinfo(&addr, sizeof(struct sockaddr), hbuf, sizeof(hbuf), nullptr, 0, 0) != 0) {
3096 Error("GetSockName", "getnameinfo failed");
3097 ia.fHostname = "????";
3098 } else
3099 ia.fHostname = hbuf;
3100
3101 return ia;
3102}
3103
3104////////////////////////////////////////////////////////////////////////////////
3105/// Get Internet Protocol (IP) address of remote host and port #.
3106
3108{
3109 struct sockaddr addr;
3110#if defined(USE_SIZE_T)
3111 size_t len = sizeof(addr);
3112#elif defined(USE_SOCKLEN_T)
3113 socklen_t len = sizeof(addr);
3114#else
3115 int len = sizeof(addr);
3116#endif
3117
3118 TInetAddress ia;
3119 if (getpeername(sock, &addr, &len) == -1) {
3120 SysError("GetPeerName", "getpeername failed");
3121 return ia;
3122 }
3123
3124 if (addr.sa_family != AF_INET) return ia; // only IPv4
3125 ia.fFamily = addr.sa_family;
3126 struct sockaddr_in *addrin = (struct sockaddr_in *)&addr;
3127 ia.fPort = ntohs(addrin->sin_port);
3128 ia.fAddresses[0] = ntohl(addrin->sin_addr.s_addr);
3129
3130 char hbuf[NI_MAXHOST];
3131 if (getnameinfo(&addr, sizeof(struct sockaddr), hbuf, sizeof(hbuf), nullptr, 0, 0) != 0) {
3132 Error("GetPeerName", "getnameinfo failed");
3133 ia.fHostname = "????";
3134 } else
3135 ia.fHostname = hbuf;
3136
3137 return ia;
3138}
3139
3140////////////////////////////////////////////////////////////////////////////////
3141/// Get port # of internet service.
3142
3143int TUnixSystem::GetServiceByName(const char *servicename)
3144{
3145 struct servent *sp;
3146
3147 if ((sp = getservbyname(servicename, kProtocolName)) == 0) {
3148 Error("GetServiceByName", "no service \"%s\" with protocol \"%s\"\n",
3149 servicename, kProtocolName);
3150 return -1;
3151 }
3152 return ntohs(sp->s_port);
3153}
3154
3155////////////////////////////////////////////////////////////////////////////////
3156/// Get name of internet service.
3157
3159{
3160 struct servent *sp;
3161
3162 if ((sp = getservbyport(htons(port), kProtocolName)) == 0) {
3163 //::Error("GetServiceByPort", "no service \"%d\" with protocol \"%s\"",
3164 // port, kProtocolName);
3165 return Form("%d", port);
3166 }
3167 return sp->s_name;
3168}
3169
3170////////////////////////////////////////////////////////////////////////////////
3171/// Connect to service servicename on server servername.
3172
3173int TUnixSystem::ConnectService(const char *servername, int port,
3174 int tcpwindowsize, const char *protocol)
3175{
3176 if (!strcmp(servername, "unix")) {
3177 return UnixUnixConnect(port);
3178 } else if (!gSystem->AccessPathName(servername) || servername[0] == '/') {
3179 return UnixUnixConnect(servername);
3180 }
3181
3182 if (!strcmp(protocol, "udp")){
3183 return UnixUdpConnect(servername, port);
3184 }
3185
3186 return UnixTcpConnect(servername, port, tcpwindowsize);
3187}
3188
3189////////////////////////////////////////////////////////////////////////////////
3190/// Open a connection to a service on a server. Returns -1 in case
3191/// connection cannot be opened.
3192/// Use tcpwindowsize to specify the size of the receive buffer, it has
3193/// to be specified here to make sure the window scale option is set (for
3194/// tcpwindowsize > 65KB and for platforms supporting window scaling).
3195/// Is called via the TSocket constructor.
3196
3197int TUnixSystem::OpenConnection(const char *server, int port, int tcpwindowsize, const char *protocol)
3198{
3199 return ConnectService(server, port, tcpwindowsize, protocol);
3200}
3201
3202////////////////////////////////////////////////////////////////////////////////
3203/// Announce TCP/IP service.
3204/// Open a socket, bind to it and start listening for TCP/IP connections
3205/// on the port. If reuse is true reuse the address, backlog specifies
3206/// how many sockets can be waiting to be accepted.
3207/// Use tcpwindowsize to specify the size of the receive buffer, it has
3208/// to be specified here to make sure the window scale option is set (for
3209/// tcpwindowsize > 65KB and for platforms supporting window scaling).
3210/// Returns socket fd or -1 if socket() failed, -2 if bind() failed
3211/// or -3 if listen() failed.
3212
3213int TUnixSystem::AnnounceTcpService(int port, Bool_t reuse, int backlog,
3214 int tcpwindowsize)
3215{
3216 return UnixTcpService(port, reuse, backlog, tcpwindowsize);
3217}
3218
3219////////////////////////////////////////////////////////////////////////////////
3220/// Announce UDP service.
3221
3222int TUnixSystem::AnnounceUdpService(int port, int backlog)
3223{
3224 return UnixUdpService(port, backlog);
3225}
3226
3227////////////////////////////////////////////////////////////////////////////////
3228/// Announce unix domain service on path "kServerPath/<port>"
3229
3230int TUnixSystem::AnnounceUnixService(int port, int backlog)
3231{
3232 return UnixUnixService(port, backlog);
3233}
3234
3235////////////////////////////////////////////////////////////////////////////////
3236/// Announce unix domain service on path 'sockpath'
3237
3238int TUnixSystem::AnnounceUnixService(const char *sockpath, int backlog)
3239{
3240 return UnixUnixService(sockpath, backlog);
3241}
3242
3243////////////////////////////////////////////////////////////////////////////////
3244/// Accept a connection. In case of an error return -1. In case
3245/// non-blocking I/O is enabled and no connections are available
3246/// return -2.
3247
3249{
3250 int soc = -1;
3251
3252 while ((soc = ::accept(sock, 0, 0)) == -1 && GetErrno() == EINTR)
3253 ResetErrno();
3254
3255 if (soc == -1) {
3256 if (GetErrno() == EWOULDBLOCK)
3257 return -2;
3258 else {
3259 SysError("AcceptConnection", "accept");
3260 return -1;
3261 }
3262 }
3263
3264 return soc;
3265}
3266
3267////////////////////////////////////////////////////////////////////////////////
3268/// Close socket.
3269
3271{
3272 if (sock < 0) return;
3273
3274#if !defined(R__AIX) || defined(_AIX41) || defined(_AIX43)
3275 if (force)
3276 ::shutdown(sock, 2); // will also close connection of parent
3277#endif
3278
3279 while (::close(sock) == -1 && GetErrno() == EINTR)
3280 ResetErrno();
3281}
3282
3283////////////////////////////////////////////////////////////////////////////////
3284/// Receive a buffer headed by a length indicator. Length is the size of
3285/// the buffer. Returns the number of bytes received in buf or -1 in
3286/// case of error.
3287
3288int TUnixSystem::RecvBuf(int sock, void *buf, int length)
3289{
3290 Int_t header;
3291
3292 if (UnixRecv(sock, &header, sizeof(header), 0) > 0) {
3293 int count = ntohl(header);
3294
3295 if (count > length) {
3296 Error("RecvBuf", "record header exceeds buffer size");
3297 return -1;
3298 } else if (count > 0) {
3299 if (UnixRecv(sock, buf, count, 0) < 0) {
3300 Error("RecvBuf", "cannot receive buffer");
3301 return -1;
3302 }
3303 }
3304 return count;
3305 }
3306 return -1;
3307}
3308
3309////////////////////////////////////////////////////////////////////////////////
3310/// Send a buffer headed by a length indicator. Returns length of sent buffer
3311/// or -1 in case of error.
3312
3313int TUnixSystem::SendBuf(int sock, const void *buf, int length)
3314{
3315 Int_t header = htonl(length);
3316
3317 if (UnixSend(sock, &header, sizeof(header), 0) < 0) {
3318 Error("SendBuf", "cannot send header");
3319 return -1;
3320 }
3321 if (length > 0) {
3322 if (UnixSend(sock, buf, length, 0) < 0) {
3323 Error("SendBuf", "cannot send buffer");
3324 return -1;
3325 }
3326 }
3327 return length;
3328}
3329
3330////////////////////////////////////////////////////////////////////////////////
3331/// Receive exactly length bytes into buffer. Use opt to receive out-of-band
3332/// data or to have a peek at what is in the buffer (see TSocket). Buffer
3333/// must be able to store at least length bytes. Returns the number of
3334/// bytes received (can be 0 if other side of connection was closed) or -1
3335/// in case of error, -2 in case of MSG_OOB and errno == EWOULDBLOCK, -3
3336/// in case of MSG_OOB and errno == EINVAL and -4 in case of kNoBlock and
3337/// errno == EWOULDBLOCK. Returns -5 if pipe broken or reset by peer
3338/// (EPIPE || ECONNRESET).
3339
3340int TUnixSystem::RecvRaw(int sock, void *buf, int length, int opt)
3341{
3342 int flag;
3343
3344 switch (opt) {
3345 case kDefault:
3346 flag = 0;
3347 break;
3348 case kOob:
3349 flag = MSG_OOB;
3350 break;
3351 case kPeek:
3352 flag = MSG_PEEK;
3353 break;
3354 case kDontBlock:
3355 flag = -1;
3356 break;
3357 default:
3358 flag = 0;
3359 break;
3360 }
3361
3362 int n;
3363 if ((n = UnixRecv(sock, buf, length, flag)) <= 0) {
3364 if (n == -1 && GetErrno() != EINTR)
3365 Error("RecvRaw", "cannot receive buffer");
3366 return n;
3367 }
3368 return n;
3369}
3370
3371////////////////////////////////////////////////////////////////////////////////
3372/// Send exactly length bytes from buffer. Use opt to send out-of-band
3373/// data (see TSocket). Returns the number of bytes sent or -1 in case of
3374/// error. Returns -4 in case of kNoBlock and errno == EWOULDBLOCK.
3375/// Returns -5 if pipe broken or reset by peer (EPIPE || ECONNRESET).
3376
3377int TUnixSystem::SendRaw(int sock, const void *buf, int length, int opt)
3378{
3379 int flag;
3380
3381 switch (opt) {
3382 case kDefault:
3383 flag = 0;
3384 break;
3385 case kOob:
3386 flag = MSG_OOB;
3387 break;
3388 case kDontBlock:
3389 flag = -1;
3390 break;
3391 case kPeek: // receive only option (see RecvRaw)
3392 default:
3393 flag = 0;
3394 break;
3395 }
3396
3397 int n;
3398 if ((n = UnixSend(sock, buf, length, flag)) <= 0) {
3399 if (n == -1 && GetErrno() != EINTR)
3400 Error("SendRaw", "cannot send buffer");
3401 return n;
3402 }
3403 return n;
3404}
3405
3406////////////////////////////////////////////////////////////////////////////////
3407/// Set socket option.
3408
3409int TUnixSystem::SetSockOpt(int sock, int opt, int val)
3410{
3411 if (sock < 0) return -1;
3412
3413 switch (opt) {
3414 case kSendBuffer:
3415 if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, sizeof(val)) == -1) {
3416 SysError("SetSockOpt", "setsockopt(SO_SNDBUF)");
3417 return -1;
3418 }
3419 break;
3420 case kRecvBuffer:
3421 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, sizeof(val)) == -1) {
3422 SysError("SetSockOpt", "setsockopt(SO_RCVBUF)");
3423 return -1;
3424 }
3425 break;
3426 case kOobInline:
3427 if (setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char*)&val, sizeof(val)) == -1) {
3428 SysError("SetSockOpt", "setsockopt(SO_OOBINLINE)");
3429 return -1;
3430 }
3431 break;
3432 case kKeepAlive:
3433 if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(val)) == -1) {
3434 SysError("SetSockOpt", "setsockopt(SO_KEEPALIVE)");
3435 return -1;
3436 }
3437 break;
3438 case kReuseAddr:
3439 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val)) == -1) {
3440 SysError("SetSockOpt", "setsockopt(SO_REUSEADDR)");
3441 return -1;
3442 }
3443 break;
3444 case kNoDelay:
3445 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(val)) == -1) {
3446 SysError("SetSockOpt", "setsockopt(TCP_NODELAY)");
3447 return -1;
3448 }
3449 break;
3450 case kNoBlock:
3451 if (ioctl(sock, FIONBIO, (char*)&val) == -1) {
3452 SysError("SetSockOpt", "ioctl(FIONBIO)");
3453 return -1;
3454 }
3455 break;
3456 case kProcessGroup:
3457#ifndef R__WINGCC
3458 if (ioctl(sock, SIOCSPGRP, (char*)&val) == -1) {
3459 SysError("SetSockOpt", "ioctl(SIOCSPGRP)");
3460 return -1;
3461 }
3462#else
3463 Error("SetSockOpt", "ioctl(SIOCGPGRP) not supported on cygwin/gcc");
3464 return -1;
3465#endif
3466 break;
3467 case kAtMark: // read-only option (see GetSockOpt)
3468 case kBytesToRead: // read-only option
3469 default:
3470 Error("SetSockOpt", "illegal option (%d)", opt);
3471 return -1;
3472 }
3473 return 0;
3474}
3475
3476////////////////////////////////////////////////////////////////////////////////
3477/// Get socket option.
3478
3479int TUnixSystem::GetSockOpt(int sock, int opt, int *val)
3480{
3481 if (sock < 0) return -1;
3482
3483#if defined(USE_SOCKLEN_T) || defined(_AIX43)
3484 socklen_t optlen = sizeof(*val);
3485#elif defined(USE_SIZE_T)
3486 size_t optlen = sizeof(*val);
3487#else
3488 int optlen = sizeof(*val);
3489#endif
3490
3491 switch (opt) {
3492 case kSendBuffer:
3493 if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)val, &optlen) == -1) {
3494 SysError("GetSockOpt", "getsockopt(SO_SNDBUF)");
3495 return -1;
3496 }
3497 break;
3498 case kRecvBuffer:
3499 if (getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)val, &optlen) == -1) {
3500 SysError("GetSockOpt", "getsockopt(SO_RCVBUF)");
3501 return -1;
3502 }
3503 break;
3504 case kOobInline:
3505 if (getsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char*)val, &optlen) == -1) {
3506 SysError("GetSockOpt", "getsockopt(SO_OOBINLINE)");
3507 return -1;
3508 }
3509 break;
3510 case kKeepAlive:
3511 if (getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)val, &optlen) == -1) {
3512 SysError("GetSockOpt", "getsockopt(SO_KEEPALIVE)");
3513 return -1;
3514 }
3515 break;
3516 case kReuseAddr:
3517 if (getsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)val, &optlen) == -1) {
3518 SysError("GetSockOpt", "getsockopt(SO_REUSEADDR)");
3519 return -1;
3520 }
3521 break;
3522 case kNoDelay:
3523 if (getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)val, &optlen) == -1) {
3524 SysError("GetSockOpt", "getsockopt(TCP_NODELAY)");
3525 return -1;
3526 }
3527 break;
3528 case kNoBlock:
3529 int flg;
3530 if ((flg = fcntl(sock, F_GETFL, 0)) == -1) {
3531 SysError("GetSockOpt", "fcntl(F_GETFL)");
3532 return -1;
3533 }
3534 *val = flg & O_NDELAY;
3535 break;
3536 case kProcessGroup:
3537#if !defined(R__LYNXOS) && !defined(R__WINGCC)
3538 if (ioctl(sock, SIOCGPGRP, (char*)val) == -1) {
3539 SysError("GetSockOpt", "ioctl(SIOCGPGRP)");
3540 return -1;
3541 }
3542#else
3543 Error("GetSockOpt", "ioctl(SIOCGPGRP) not supported on LynxOS and cygwin/gcc");
3544 return -1;
3545#endif
3546 break;
3547 case kAtMark:
3548#if !defined(R__LYNXOS)
3549 if (ioctl(sock, SIOCATMARK, (char*)val) == -1) {
3550 SysError("GetSockOpt", "ioctl(SIOCATMARK)");
3551 return -1;
3552 }
3553#else
3554 Error("GetSockOpt", "ioctl(SIOCATMARK) not supported on LynxOS");
3555 return -1;
3556#endif
3557 break;
3558 case kBytesToRead:
3559#if !defined(R__LYNXOS)
3560 if (ioctl(sock, FIONREAD, (char*)val) == -1) {
3561 SysError("GetSockOpt", "ioctl(FIONREAD)");
3562 return -1;
3563 }
3564#else
3565 Error("GetSockOpt", "ioctl(FIONREAD) not supported on LynxOS");
3566 return -1;
3567#endif
3568 break;
3569 default:
3570 Error("GetSockOpt", "illegal option (%d)", opt);
3571 *val = 0;
3572 return -1;
3573 }
3574 return 0;
3575}
3576
3577//////////////////////////////////////////////////////////////////////////
3578// //
3579// Static Protected Unix Interface functions. //
3580// //
3581//////////////////////////////////////////////////////////////////////////
3582
3583//---- signals -----------------------------------------------------------------
3584
3585static struct Signalmap_t {
3586 int fCode;
3587 SigHandler_t fHandler;
3588 struct sigaction *fOldHandler;
3589 const char *fSigName;
3590} gSignalMap[kMAXSIGNALS] = { // the order of the signals should be identical
3591 { SIGBUS, 0, 0, "bus error" }, // to the one in TSysEvtHandler.h
3592 { SIGSEGV, 0, 0, "segmentation violation" },
3593 { SIGSYS, 0, 0, "bad argument to system call" },
3594 { SIGPIPE, 0, 0, "write on a pipe with no one to read it" },
3595 { SIGILL, 0, 0, "illegal instruction" },
3596 { SIGQUIT, 0, 0, "quit" },
3597 { SIGINT, 0, 0, "interrupt" },
3598 { SIGWINCH, 0, 0, "window size change" },
3599 { SIGALRM, 0, 0, "alarm clock" },
3600 { SIGCHLD, 0, 0, "death of a child" },
3601 { SIGURG, 0, 0, "urgent data arrived on an I/O channel" },
3602 { SIGFPE, 0, 0, "floating point exception" },
3603 { SIGTERM, 0, 0, "termination signal" },
3604 { SIGUSR1, 0, 0, "user-defined signal 1" },
3605 { SIGUSR2, 0, 0, "user-defined signal 2" }
3607
3608
3609////////////////////////////////////////////////////////////////////////////////
3610/// Call the signal handler associated with the signal.
3611
3612static void sighandler(int sig)
3613{
3614 for (int i= 0; i < kMAXSIGNALS; i++) {
3615 if (gSignalMap[i].fCode == sig) {
3616 (*gSignalMap[i].fHandler)((ESignals)i);
3617 return;
3618 }
3619 }
3620}
3621
3622////////////////////////////////////////////////////////////////////////////////
3623/// Handle and dispatch signals.
3624
3626{
3627 switch (sig) {
3628 case kSigAlarm:
3630 break;
3631 case kSigChild:
3632 CheckChilds();
3633 break;
3634 case kSigBus:
3638 Break("TUnixSystem::DispatchSignals", "%s", UnixSigname(sig));
3639 StackTrace();
3640 if (gApplication)
3641 //sig is ESignal, should it be mapped to the correct signal number?
3643 else
3644 //map to the real signal code + set the
3645 //high order bit to indicate a signal (?)
3646 Exit(gSignalMap[sig].fCode + 0x80);
3647 break;
3648 case kSigSystem:
3649 case kSigPipe:
3650 Break("TUnixSystem::DispatchSignals", "%s", UnixSigname(sig));
3651 break;
3652 case kSigWindowChanged:
3653 Gl_windowchanged();
3654 break;
3655 case kSigUser2:
3656 Break("TUnixSystem::DispatchSignals", "%s: printing stacktrace", UnixSigname(sig));
3657 StackTrace();
3658 // Intentional fall-through; pass the signal to handlers (or terminate):
3659 default:
3660 fSignals->Set(sig);
3661 fSigcnt++;
3662 break;
3663 }
3664
3665 // check a-synchronous signals
3666 if (fSigcnt > 0 && fSignalHandler->GetSize() > 0)
3668}
3669
3670////////////////////////////////////////////////////////////////////////////////
3671/// Set a signal handler for a signal.
3672
3674{
3675 if (gEnv && !gEnv->GetValue("Root.ErrorHandlers", 1))
3676 return;
3677
3678 if (gSignalMap[sig].fHandler != handler) {
3679 struct sigaction sigact;
3680
3681 gSignalMap[sig].fHandler = handler;
3682 gSignalMap[sig].fOldHandler = new struct sigaction();
3683
3684#if defined(R__SUN)
3685 sigact.sa_handler = (void (*)())sighandler;
3686#elif defined(R__SOLARIS)
3687 sigact.sa_handler = sighandler;
3688#elif defined(R__LYNXOS)
3689# if (__GNUG__>=3)
3690 sigact.sa_handler = sighandler;
3691# else
3692 sigact.sa_handler = (void (*)(...))sighandler;
3693# endif
3694#else
3695 sigact.sa_handler = sighandler;
3696#endif
3697 sigemptyset(&sigact.sa_mask);
3698 sigact.sa_flags = 0;
3699#if defined(SA_RESTART)
3700 sigact.sa_flags |= SA_RESTART;
3701#endif
3702 if (sigaction(gSignalMap[sig].fCode, &sigact,
3703 gSignalMap[sig].fOldHandler) < 0)
3704 ::SysError("TUnixSystem::UnixSignal", "sigaction");
3705 }
3706}
3707
3708////////////////////////////////////////////////////////////////////////////////
3709/// If ignore is true ignore the specified signal, else restore previous
3710/// behaviour.
3711
3713{
3714 TTHREAD_TLS(Bool_t) ignoreSig[kMAXSIGNALS] = { kFALSE };
3715 TTHREAD_TLS_ARRAY(struct sigaction,kMAXSIGNALS,oldsigact);
3716
3717 if (ignore != ignoreSig[sig]) {
3718 ignoreSig[sig] = ignore;
3719 if (ignore) {
3720 struct sigaction sigact;
3721#if defined(R__SUN)
3722 sigact.sa_handler = (void (*)())SIG_IGN;
3723#elif defined(R__SOLARIS)
3724 sigact.sa_handler = (void (*)(int))SIG_IGN;
3725#else
3726 sigact.sa_handler = SIG_IGN;
3727#endif
3728 sigemptyset(&sigact.sa_mask);
3729 sigact.sa_flags = 0;
3730 if (sigaction(gSignalMap[sig].fCode, &sigact, &oldsigact[sig]) < 0)
3731 ::SysError("TUnixSystem::UnixIgnoreSignal", "sigaction");
3732 } else {
3733 if (sigaction(gSignalMap[sig].fCode, &oldsigact[sig], 0) < 0)
3734 ::SysError("TUnixSystem::UnixIgnoreSignal", "sigaction");
3735 }
3736 }
3737}
3738
3739////////////////////////////////////////////////////////////////////////////////
3740/// When the argument is true the SIGALRM signal handler is set so that
3741/// interrupted syscalls will not be restarted by the kernel. This is
3742/// typically used in case one wants to put a timeout on an I/O operation.
3743/// By default interrupted syscalls will always be restarted (for all
3744/// signals). This can be controlled for each a-synchronous TTimer via
3745/// the method TTimer::SetInterruptSyscalls().
3746
3748{
3749 if (gSignalMap[kSigAlarm].fHandler) {
3750 struct sigaction sigact;
3751#if defined(R__SUN)
3752 sigact.sa_handler = (void (*)())sighandler;
3753#elif defined(R__SOLARIS)
3754 sigact.sa_handler = sighandler;
3755#elif defined(R__LYNXOS)
3756# if (__GNUG__>=3)
3757 sigact.sa_handler = sighandler;
3758# else
3759 sigact.sa_handler = (void (*)(...))sighandler;
3760# endif
3761#else
3762 sigact.sa_handler = sighandler;
3763#endif
3764 sigemptyset(&sigact.sa_mask);
3765 sigact.sa_flags = 0;
3766 if (set) {
3767#if defined(SA_INTERRUPT) // SunOS
3768 sigact.sa_flags |= SA_INTERRUPT;
3769#endif
3770 } else {
3771#if defined(SA_RESTART)
3772 sigact.sa_flags |= SA_RESTART;
3773#endif
3774 }
3775 if (sigaction(gSignalMap[kSigAlarm].fCode, &sigact, 0) < 0)
3776 ::SysError("TUnixSystem::UnixSigAlarmInterruptsSyscalls", "sigaction");
3777 }
3778}
3779
3780////////////////////////////////////////////////////////////////////////////////
3781/// Return the signal name associated with a signal.
3782
3784{
3785 return gSignalMap[sig].fSigName;
3786}
3787
3788////////////////////////////////////////////////////////////////////////////////
3789/// Restore old signal handler for specified signal.
3790
3792{
3793 if (gSignalMap[sig].fOldHandler) {
3794 // restore old signal handler
3795 if (sigaction(gSignalMap[sig].fCode, gSignalMap[sig].fOldHandler, 0) < 0)
3796 ::SysError("TUnixSystem::UnixSignal", "sigaction");
3797 delete gSignalMap[sig].fOldHandler;
3798 gSignalMap[sig].fOldHandler = 0;
3799 gSignalMap[sig].fHandler = 0;
3800 }
3801}
3802
3803////////////////////////////////////////////////////////////////////////////////
3804/// Restore old signal handlers.
3805
3807{
3808 for (int sig = 0; sig < kMAXSIGNALS; sig++)
3810}
3811
3812//---- time --------------------------------------------------------------------
3813
3814////////////////////////////////////////////////////////////////////////////////
3815/// Get current time in milliseconds since 0:00 Jan 1 1995.
3816
3818{
3819 static std::atomic<time_t> jan95{0};
3820 if (!jan95) {
3821 struct tm tp;
3822 tp.tm_year = 95;
3823 tp.tm_mon = 0;
3824 tp.tm_mday = 1;
3825 tp.tm_hour = 0;
3826 tp.tm_min = 0;
3827 tp.tm_sec = 0;
3828 tp.tm_isdst = -1;
3829
3830 jan95 = mktime(&tp);
3831 if ((int)jan95 == -1) {
3832 ::SysError("TUnixSystem::UnixNow", "error converting 950001 0:00 to time_t");
3833 return 0;
3834 }
3835 }
3836
3837 struct timeval t;
3838 gettimeofday(&t, 0);
3839 return Long64_t(t.tv_sec-(Long_t)jan95)*1000 + t.tv_usec/1000;
3840}
3841
3842////////////////////////////////////////////////////////////////////////////////
3843/// Set interval timer to time-out in ms milliseconds.
3844
3846{
3847 struct itimerval itv;
3848 itv.it_value.tv_sec = 0;
3849 itv.it_value.tv_usec = 0;
3850 itv.it_interval.tv_sec = 0;
3851 itv.it_interval.tv_usec = 0;
3852 if (ms > 0) {
3853 itv.it_value.tv_sec = time_t(ms / 1000);
3854 itv.it_value.tv_usec = time_t((ms % 1000) * 1000);
3855 }
3856 int st = setitimer(ITIMER_REAL, &itv, 0);
3857 if (st == -1)
3858 ::SysError("TUnixSystem::UnixSetitimer", "setitimer");
3859 return st;
3860}
3861
3862//---- file descriptors --------------------------------------------------------
3863
3864////////////////////////////////////////////////////////////////////////////////
3865/// Wait for events on the file descriptors specified in the readready and
3866/// writeready masks or for timeout (in milliseconds) to occur. Returns
3867/// the number of ready descriptors, or 0 in case of timeout, or < 0 in
3868/// case of an error, with -2 being EINTR and -3 EBADF. In case of EINTR
3869/// the errno has been reset and the method can be called again.
3870
3871int TUnixSystem::UnixSelect(Int_t nfds, TFdSet *readready, TFdSet *writeready,
3872 Long_t timeout)
3873{
3874 int retcode;
3875
3876 fd_set *rd = (readready) ? (fd_set*)readready->GetBits() : 0;
3877 fd_set *wr = (writeready) ? (fd_set*)writeready->GetBits() : 0;
3878
3879 if (timeout >= 0) {
3880 struct timeval tv;
3881 tv.tv_sec = Int_t(timeout / 1000);
3882 tv.tv_usec = (timeout % 1000) * 1000;
3883 retcode = select(nfds, rd, wr, 0, &tv);
3884 } else {
3885 retcode = select(nfds, rd, wr, 0, 0);
3886 }
3887 if (retcode == -1) {
3888 if (GetErrno() == EINTR) {
3889 ResetErrno(); // errno is not self reseting
3890 return -2;
3891 }
3892 if (GetErrno() == EBADF)
3893 return -3;
3894 return -1;
3895 }
3896
3897 return retcode;
3898}
3899
3900//---- directories -------------------------------------------------------------
3901
3902////////////////////////////////////////////////////////////////////////////////
3903/// Returns the user's home directory.
3904
3905const char *TUnixSystem::UnixHomedirectory(const char *name)
3906{
3907 static char path[kMAXPATHLEN], mydir[kMAXPATHLEN] = { '\0' };
3908 return UnixHomedirectory(name, path, mydir);
3909}
3910
3911////////////////////////////////////////////////////////////////////////////
3912/// Returns the user's home directory.
3913
3914const char *TUnixSystem::UnixHomedirectory(const char *name, char *path, char *mydir)
3915{
3916 struct passwd *pw;
3917 if (name) {
3918 pw = getpwnam(name);
3919 if (pw) {
3920 strncpy(path, pw->pw_dir, kMAXPATHLEN-1);
3921 path[kMAXPATHLEN-1] = '\0';
3922 return path;
3923 }
3924 } else {
3925 if (mydir[0])
3926 return mydir;
3927 pw = getpwuid(getuid());
3928 if (pw && pw->pw_dir) {
3929 strncpy(mydir, pw->pw_dir, kMAXPATHLEN-1);
3930 mydir[kMAXPATHLEN-1] = '\0';
3931 return mydir;
3932 } else if (gSystem->Getenv("HOME")) {
3933 strncpy(mydir, gSystem->Getenv("HOME"), kMAXPATHLEN-1);
3934 mydir[kMAXPATHLEN-1] = '\0';
3935 return mydir;
3936 }
3937 }
3938 return 0;
3939}
3940
3941////////////////////////////////////////////////////////////////////////////////
3942/// Make a Unix file system directory. Returns 0 in case of success and
3943/// -1 if the directory could not be created (either already exists or
3944/// illegal path name).
3945
3946int TUnixSystem::UnixMakedir(const char *dir)
3947{
3948 return ::mkdir(StripOffProto(dir, "file:"), 0755);
3949}
3950
3951////////////////////////////////////////////////////////////////////////////////
3952/// Open a directory.
3953
3954void *TUnixSystem::UnixOpendir(const char *dir)
3955{
3956 struct stat finfo;
3957
3958 const char *edir = StripOffProto(dir, "file:");
3959
3960 if (stat(edir, &finfo) < 0)
3961 return 0;
3962
3963 if (!S_ISDIR(finfo.st_mode))
3964 return 0;
3965
3966 return (void*) opendir(edir);
3967}
3968
3969#if defined(_POSIX_SOURCE)
3970// Posix does not require that the d_ino field be present, and some
3971// systems do not provide it.
3972# define REAL_DIR_ENTRY(dp) 1
3973#else
3974# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
3975#endif
3976
3977////////////////////////////////////////////////////////////////////////////////
3978/// Returns the next directory entry.
3979
3980const char *TUnixSystem::UnixGetdirentry(void *dirp1)
3981{
3982 DIR *dirp = (DIR*)dirp1;
3983#ifdef HAS_DIRENT
3984 struct dirent *dp;
3985#else
3986 struct direct *dp;
3987#endif
3988
3989 if (dirp) {
3990 for (;;) {
3991 dp = readdir(dirp);
3992 if (dp == 0)
3993 return 0;
3994 if (REAL_DIR_ENTRY(dp))
3995 return dp->d_name;
3996 }
3997 }
3998 return 0;
3999}
4000
4001//---- files -------------------------------------------------------------------
4002
4003////////////////////////////////////////////////////////////////////////////////
4004/// Get info about a file. Info is returned in the form of a FileStat_t
4005/// structure (see TSystem.h).
4006/// The function returns 0 in case of success and 1 if the file could
4007/// not be stat'ed.
4008
4009int TUnixSystem::UnixFilestat(const char *fpath, FileStat_t &buf)
4010{
4011 const char *path = StripOffProto(fpath, "file:");
4012 buf.fIsLink = kFALSE;
4013
4014#if defined(R__SEEK64)
4015 struct stat64 sbuf;
4016 if (path && lstat64(path, &sbuf) == 0) {
4017#else
4018 struct stat sbuf;
4019 if (path && lstat(path, &sbuf) == 0) {
4020#endif
4021 buf.fIsLink = S_ISLNK(sbuf.st_mode);
4022 if (buf.fIsLink) {
4023#if defined(R__SEEK64)
4024 if (stat64(path, &sbuf) == -1) {
4025#else
4026 if (stat(path, &sbuf) == -1) {
4027#endif
4028 return 1;
4029 }
4030 }
4031 buf.fDev = sbuf.st_dev;
4032 buf.fIno = sbuf.st_ino;
4033 buf.fMode = sbuf.st_mode;
4034 buf.fUid = sbuf.st_uid;
4035 buf.fGid = sbuf.st_gid;
4036 buf.fSize = sbuf.st_size;
4037 buf.fMtime = sbuf.st_mtime;
4038
4039 return 0;
4040 }
4041 return 1;
4042}
4043
4044////////////////////////////////////////////////////////////////////////////////
4045/// Get info about a file system: id, bsize, bfree, blocks.
4046/// Id is file system type (machine dependend, see statfs())
4047/// Bsize is block size of file system
4048/// Blocks is total number of blocks in file system
4049/// Bfree is number of free blocks in file system
4050/// The function returns 0 in case of success and 1 if the file system could
4051/// not be stat'ed.
4052
4053int TUnixSystem::UnixFSstat(const char *path, Long_t *id, Long_t *bsize,
4054 Long_t *blocks, Long_t *bfree)
4055{
4056 struct statfs statfsbuf;
4057#if (defined(R__SOLARIS) && !defined(R__LINUX))
4058 if (statfs(path, &statfsbuf, sizeof(struct statfs), 0) == 0) {
4059 *id = statfsbuf.f_fstyp;
4060 *bsize = statfsbuf.f_bsize;
4061 *blocks = statfsbuf.f_blocks;
4062 *bfree = statfsbuf.f_bfree;
4063#else
4064 if (statfs((char*)path, &statfsbuf) == 0) {
4065#ifdef R__OBSD
4066 // Convert BSD filesystem names to Linux filesystem type numbers
4067 // where possible. Linux statfs uses a value of -1 to indicate
4068 // an unsupported field.
4069
4070 if (!strcmp(statfsbuf.f_fstypename, MOUNT_FFS) ||
4071 !strcmp(statfsbuf.f_fstypename, MOUNT_MFS))
4072 *id = 0x11954;
4073 else if (!strcmp(statfsbuf.f_fstypename, MOUNT_NFS))
4074 *id = 0x6969;
4075 else if (!strcmp(statfsbuf.f_fstypename, MOUNT_MSDOS))
4076 *id = 0x4d44;
4077 else if (!strcmp(statfsbuf.f_fstypename, MOUNT_EXT2FS))
4078 *id = 0xef53;
4079 else if (!strcmp(statfsbuf.f_fstypename, MOUNT_CD9660))
4080 *id = 0x9660;
4081 else if (!strcmp(statfsbuf.f_fstypename, MOUNT_NCPFS))
4082 *id = 0x6969;
4083 else
4084 *id = -1;
4085#else
4086 *id = statfsbuf.f_type;
4087#endif
4088 *bsize = statfsbuf.f_bsize;
4089 *blocks = statfsbuf.f_blocks;
4090 *bfree = statfsbuf.f_bavail;
4091#endif
4092 return 0;
4093 }
4094 return 1;
4095}
4096
4097////////////////////////////////////////////////////////////////////////////////
4098/// Wait till child is finished.
4099
4101{
4102 int status;
4103 return (int) waitpid(0, &status, WNOHANG);
4104}
4105
4106//---- RPC -------------------------------------------------------------------
4107
4108////////////////////////////////////////////////////////////////////////////////
4109/// Open a TCP/IP connection to server and connect to a service (i.e. port).
4110/// Use tcpwindowsize to specify the size of the receive buffer, it has
4111/// to be specified here to make sure the window scale option is set (for
4112/// tcpwindowsize > 65KB and for platforms supporting window scaling).
4113/// Is called via the TSocket constructor. Returns -1 in case of error.
4114
4115int TUnixSystem::UnixTcpConnect(const char *hostname, int port,
4116 int tcpwindowsize)
4117{
4118 short sport;
4119 struct servent *sp;
4120
4121 if ((sp = getservbyport(htons(port), kProtocolName)))
4122 sport = sp->s_port;
4123 else
4124 sport = htons(port);
4125
4126 TInetAddress addr = gSystem->GetHostByName(hostname);
4127 if (!addr.IsValid()) return -1;
4128 UInt_t adr = htonl(addr.GetAddress());
4129
4130 struct sockaddr_in server;
4131 memset(&server, 0, sizeof(server));
4132 memcpy(&server.sin_addr, &adr, sizeof(adr));
4133 server.sin_family = addr.GetFamily();
4134 server.sin_port = sport;
4135
4136 // Create socket
4137 int sock;
4138 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
4139 ::SysError("TUnixSystem::UnixTcpConnect", "socket (%s:%d)",
4140 hostname, port);
4141 return -1;
4142 }
4143
4144 if (tcpwindowsize > 0) {
4145 gSystem->SetSockOpt(sock, kRecvBuffer, tcpwindowsize);
4146 gSystem->SetSockOpt(sock, kSendBuffer, tcpwindowsize);
4147 }
4148
4149 while (connect(sock, (struct sockaddr*) &server, sizeof(server)) == -1) {
4150 if (GetErrno() == EINTR)
4151 ResetErrno();
4152 else {
4153 ::SysError("TUnixSystem::UnixTcpConnect", "connect (%s:%d)",
4154 hostname, port);
4155 close(sock);
4156 return -1;
4157 }
4158 }
4159 return sock;
4160}
4161
4162
4163////////////////////////////////////////////////////////////////////////////////
4164/// Creates a UDP socket connection
4165/// Is called via the TSocket constructor. Returns -1 in case of error.
4166
4167int TUnixSystem::UnixUdpConnect(const char *hostname, int port)
4168{
4169 short sport;
4170 struct servent *sp;
4171
4172 if ((sp = getservbyport(htons(port), kProtocolName)))
4173 sport = sp->s_port;
4174 else
4175 sport = htons(port);
4176
4177 TInetAddress addr = gSystem->GetHostByName(hostname);
4178 if (!addr.IsValid()) return -1;
4179 UInt_t adr = htonl(addr.GetAddress());
4180
4181 struct sockaddr_in server;
4182 memset(&server, 0, sizeof(server));
4183 memcpy(&server.sin_addr, &adr, sizeof(adr));
4184 server.sin_family = addr.GetFamily();
4185 server.sin_port = sport;
4186
4187 // Create socket
4188 int sock;
4189 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
4190 ::SysError("TUnixSystem::UnixUdpConnect", "socket (%s:%d)",
4191 hostname, port);
4192 return -1;
4193 }
4194
4195 while (connect(sock, (struct sockaddr*) &server, sizeof(server)) == -1) {
4196 if (GetErrno() == EINTR)
4197 ResetErrno();
4198 else {
4199 ::SysError("TUnixSystem::UnixUdpConnect", "connect (%s:%d)",
4200 hostname, port);
4201 close(sock);
4202 return -1;
4203 }
4204 }
4205 return sock;
4206}
4207
4208////////////////////////////////////////////////////////////////////////////////
4209/// Connect to a Unix domain socket.
4210
4212{
4213 return UnixUnixConnect(TString::Format("%s/%d", kServerPath, port));
4214}
4215
4216////////////////////////////////////////////////////////////////////////////////
4217/// Connect to a Unix domain socket. Returns -1 in case of error.
4218
4219int TUnixSystem::UnixUnixConnect(const char *sockpath)
4220{
4221 if (!sockpath || strlen(sockpath) <= 0) {
4222 ::SysError("TUnixSystem::UnixUnixConnect", "socket path undefined");
4223 return -1;
4224 }
4225
4226 int sock;
4227 struct sockaddr_un unserver;
4228 unserver.sun_family = AF_UNIX;
4229
4230 if (strlen(sockpath) > sizeof(unserver.sun_path)-1) {
4231 ::Error("TUnixSystem::UnixUnixConnect", "socket path %s, longer than max allowed length (%u)",
4232 sockpath, (UInt_t)sizeof(unserver.sun_path)-1);
4233 return -1;
4234 }
4235 strcpy(unserver.sun_path, sockpath);
4236
4237 // Open socket
4238 if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
4239 ::SysError("TUnixSystem::UnixUnixConnect", "socket");
4240 return -1;
4241 }
4242
4243 while (connect(sock, (struct sockaddr*) &unserver, strlen(unserver.sun_path)+2) == -1) {
4244 if (GetErrno() == EINTR)
4245 ResetErrno();
4246 else {
4247 ::SysError("TUnixSystem::UnixUnixConnect", "connect");
4248 close(sock);
4249 return -1;
4250 }
4251 }
4252 return sock;
4253}
4254
4255////////////////////////////////////////////////////////////////////////////////
4256/// Open a socket, bind to it and start listening for TCP/IP connections
4257/// on the port. If reuse is true reuse the address, backlog specifies
4258/// how many sockets can be waiting to be accepted. If port is 0 a port
4259/// scan will be done to find a free port. This option is mutual exlusive
4260/// with the reuse option.
4261/// Use tcpwindowsize to specify the size of the receive buffer, it has
4262/// to be specified here to make sure the window scale option is set (for
4263/// tcpwindowsize > 65KB and for platforms supporting window scaling).
4264/// Returns socket fd or -1 if socket() failed, -2 if bind() failed
4265/// or -3 if listen() failed.
4266
4267int TUnixSystem::UnixTcpService(int port, Bool_t reuse, int backlog,
4268 int tcpwindowsize)
4269{
4270 const short kSOCKET_MINPORT = 5000, kSOCKET_MAXPORT = 15000;
4271 short sport, tryport = kSOCKET_MINPORT;
4272 struct servent *sp;
4273
4274 if (port == 0 && reuse) {
4275 ::Error("TUnixSystem::UnixTcpService", "cannot do a port scan while reuse is true");
4276 return -1;
4277 }
4278
4279 if ((sp = getservbyport(htons(port), kProtocolName)))
4280 sport = sp->s_port;
4281 else
4282 sport = htons(port);
4283
4284 // Create tcp socket
4285 int sock;
4286 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
4287 ::SysError("TUnixSystem::UnixTcpService", "socket");
4288 return -1;
4289 }
4290
4291 if (reuse)
4292 gSystem->SetSockOpt(sock, kReuseAddr, 1);
4293
4294 if (tcpwindowsize > 0) {
4295 gSystem->SetSockOpt(sock, kRecvBuffer, tcpwindowsize);
4296 gSystem->SetSockOpt(sock, kSendBuffer, tcpwindowsize);
4297 }
4298
4299 struct sockaddr_in inserver;
4300 memset(&inserver, 0, sizeof(inserver));
4301 inserver.sin_family = AF_INET;
4302 inserver.sin_addr.s_addr = htonl(INADDR_ANY);
4303 inserver.sin_port = sport;
4304
4305 // Bind socket
4306 if (port > 0) {
4307 if (::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver))) {
4308 ::SysError("TUnixSystem::UnixTcpService", "bind");
4309 close(sock);
4310 return -2;
4311 }
4312 } else {
4313 int bret;
4314 do {
4315 inserver.sin_port = htons(tryport);
4316 bret = ::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver));
4317 tryport++;
4318 } while (bret < 0 && GetErrno() == EADDRINUSE && tryport < kSOCKET_MAXPORT);
4319 if (bret < 0) {
4320 ::SysError("TUnixSystem::UnixTcpService", "bind (port scan)");
4321 close(sock);
4322 return -2;
4323 }
4324 }
4325
4326 // Start accepting connections
4327 if (::listen(sock, backlog)) {
4328 ::SysError("TUnixSystem::UnixTcpService", "listen");
4329 close(sock);
4330 return -3;
4331 }
4332
4333 return sock;
4334}
4335
4336////////////////////////////////////////////////////////////////////////////////
4337/// Open a socket, bind to it and start listening for UDP connections
4338/// on the port. If reuse is true reuse the address, backlog specifies
4339/// how many sockets can be waiting to be accepted. If port is 0 a port
4340/// scan will be done to find a free port. This option is mutual exlusive
4341/// with the reuse option.
4342
4343int TUnixSystem::UnixUdpService(int port, int backlog)
4344{
4345 const short kSOCKET_MINPORT = 5000, kSOCKET_MAXPORT = 15000;
4346 short sport, tryport = kSOCKET_MINPORT;
4347 struct servent *sp;
4348
4349 if ((sp = getservbyport(htons(port), kProtocolName)))
4350 sport = sp->s_port;
4351 else
4352 sport = htons(port);
4353
4354 // Create udp socket
4355 int sock;
4356 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
4357 ::SysError("TUnixSystem::UnixUdpService", "socket");
4358 return -1;
4359 }
4360
4361 struct sockaddr_in inserver;
4362 memset(&inserver, 0, sizeof(inserver));
4363 inserver.sin_family = AF_INET;
4364 inserver.sin_addr.s_addr = htonl(INADDR_ANY);
4365 inserver.sin_port = sport;
4366
4367 // Bind socket
4368 if (port > 0) {
4369 if (::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver))) {
4370 ::SysError("TUnixSystem::UnixUdpService", "bind");
4371 close(sock);
4372 return -2;
4373 }
4374 } else {
4375 int bret;
4376 do {
4377 inserver.sin_port = htons(tryport);
4378 bret = ::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver));
4379 tryport++;
4380 } while (bret < 0 && GetErrno() == EADDRINUSE && tryport < kSOCKET_MAXPORT);
4381 if (bret < 0) {
4382 ::SysError("TUnixSystem::UnixUdpService", "bind (port scan)");
4383 close(sock);
4384 return -2;
4385 }
4386 }
4387
4388 // Start accepting connections
4389 if (::listen(sock, backlog)) {
4390 ::SysError("TUnixSystem::UnixUdpService", "listen");
4391 close(sock);
4392 return -3;
4393 }
4394
4395 return sock;
4396}
4397
4398////////////////////////////////////////////////////////////////////////////////
4399/// Open a socket, bind to it and start listening for Unix domain connections
4400/// to it. Returns socket fd or -1.
4401
4402int TUnixSystem::UnixUnixService(int port, int backlog)
4403{
4404 int oldumask;
4405
4406 // Assure that socket directory exists
4407 oldumask = umask(0);
4408 int res = ::mkdir(kServerPath, 0777);
4409 umask(oldumask);
4410
4411 if (res == -1)
4412 return -1;
4413
4414 // Socket path
4415 TString sockpath;
4416 sockpath.Form("%s/%d", kServerPath, port);
4417
4418 // Remove old socket
4419 unlink(sockpath.Data());
4420
4421 return UnixUnixService(sockpath, backlog);
4422}
4423
4424////////////////////////////////////////////////////////////////////////////////
4425/// Open a socket on path 'sockpath', bind to it and start listening for Unix
4426/// domain connections to it. Returns socket fd or -1.
4427
4428int TUnixSystem::UnixUnixService(const char *sockpath, int backlog)
4429{
4430 if (!sockpath || strlen(sockpath) <= 0) {
4431 ::SysError("TUnixSystem::UnixUnixService", "socket path undefined");
4432 return -1;
4433 }
4434
4435 struct sockaddr_un unserver;
4436 int sock;
4437
4438 // Prepare structure
4439 memset(&unserver, 0, sizeof(unserver));
4440 unserver.sun_family = AF_UNIX;
4441
4442 if (strlen(sockpath) > sizeof(unserver.sun_path)-1) {
4443 ::Error("TUnixSystem::UnixUnixService", "socket path %s, longer than max allowed length (%u)",
4444 sockpath, (UInt_t)sizeof(unserver.sun_path)-1);
4445 return -1;
4446 }
4447 strcpy(unserver.sun_path, sockpath);
4448
4449 // Create socket
4450 if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
4451 ::SysError("TUnixSystem::UnixUnixService", "socket");
4452 return -1;
4453 }
4454
4455 if (::bind(sock, (struct sockaddr*) &unserver, strlen(unserver.sun_path)+2)) {
4456 ::SysError("TUnixSystem::UnixUnixService", "bind");
4457 close(sock);
4458 return -1;
4459 }
4460
4461 // Start accepting connections
4462 if (::listen(sock, backlog)) {
4463 ::SysError("TUnixSystem::UnixUnixService", "listen");
4464 close(sock);
4465 return -1;
4466 }
4467
4468 return sock;
4469}
4470
4471////////////////////////////////////////////////////////////////////////////////
4472/// Receive exactly length bytes into buffer. Returns number of bytes
4473/// received. Returns -1 in case of error, -2 in case of MSG_OOB
4474/// and errno == EWOULDBLOCK, -3 in case of MSG_OOB and errno == EINVAL
4475/// and -4 in case of kNoBlock and errno == EWOULDBLOCK.
4476/// Returns -5 if pipe broken or reset by peer (EPIPE || ECONNRESET).
4477
4478int TUnixSystem::UnixRecv(int sock, void *buffer, int length, int flag)
4479{
4480 ResetErrno();
4481
4482 if (sock < 0) return -1;
4483
4484 int once = 0;
4485 if (flag == -1) {
4486 flag = 0;
4487 once = 1;
4488 }
4489 if (flag == MSG_PEEK)
4490 once = 1;
4491
4492 int n, nrecv = 0;
4493 char *buf = (char *)buffer;
4494
4495 for (n = 0; n < length; n += nrecv) {
4496 if ((nrecv = recv(sock, buf+n, length-n, flag)) <= 0) {
4497 if (nrecv == 0)
4498 break; // EOF
4499 if (flag == MSG_OOB) {
4500 if (GetErrno() == EWOULDBLOCK)
4501 return -2;
4502 else if (GetErrno() == EINVAL)
4503 return -3;
4504 }
4505 if (GetErrno() == EWOULDBLOCK)
4506 return -4;
4507 else {
4508 if (GetErrno() != EINTR)
4509 ::SysError("TUnixSystem::UnixRecv", "recv");
4510 if (GetErrno() == EPIPE || GetErrno() == ECONNRESET)
4511 return -5;
4512 else
4513 return -1;
4514 }
4515 }
4516 if (once)
4517 return nrecv;
4518 }
4519 return n;
4520}
4521
4522////////////////////////////////////////////////////////////////////////////////
4523/// Send exactly length bytes from buffer. Returns -1 in case of error,
4524/// otherwise number of sent bytes. Returns -4 in case of kNoBlock and
4525/// errno == EWOULDBLOCK. Returns -5 if pipe broken or reset by peer
4526/// (EPIPE || ECONNRESET).
4527
4528int TUnixSystem::UnixSend(int sock, const void *buffer, int length, int flag)
4529{
4530 if (sock < 0) return -1;
4531
4532 int once = 0;
4533 if (flag == -1) {
4534 flag = 0;
4535 once = 1;
4536 }
4537
4538 int n, nsent = 0;
4539 const char *buf = (const char *)buffer;
4540
4541 for (n = 0; n < length; n += nsent) {
4542 if ((nsent = send(sock, buf+n, length-n, flag)) <= 0) {
4543 if (nsent == 0)
4544 break;
4545 if (GetErrno() == EWOULDBLOCK)
4546 return -4;
4547 else {
4548 if (GetErrno() != EINTR)
4549 ::SysError("TUnixSystem::UnixSend", "send");
4550 if (GetErrno() == EPIPE || GetErrno() == ECONNRESET)
4551 return -5;
4552 else
4553 return -1;
4554 }
4555 }
4556 if (once)
4557 return nsent;
4558 }
4559 return n;
4560}
4561
4562//---- Dynamic Loading ---------------------------------------------------------
4563
4564////////////////////////////////////////////////////////////////////////////////
4565/// Get shared library search path. Static utility function.
4566
4567static const char *DynamicPath(const char *newpath = 0, Bool_t reset = kFALSE)
4568{
4569 static TString dynpath;
4570 static Bool_t initialized = kFALSE;
4571 if (!initialized) {
4572 // force one time initialization of gROOT before we start
4573 // (otherwise it might be done as a side effect of gEnv->GetValue and
4574 // TROOT's initialization will call this routine).
4575 gROOT;
4576 }
4577
4578 if (newpath) {
4579 dynpath = newpath;
4580 } else if (reset || !initialized) {
4581 initialized = kTRUE;
4582 TString rdynpath = gEnv->GetValue("Root.DynamicPath", (char*)0);
4583 rdynpath.ReplaceAll(": ", ":"); // in case DynamicPath was extended
4584 if (rdynpath.IsNull()) {
4585 rdynpath = ".:"; rdynpath += TROOT::GetLibDir();
4586 }
4587 TString ldpath;
4588#if defined (R__AIX)
4589 ldpath = gSystem->Getenv("LIBPATH");
4590#elif defined(R__MACOSX)
4591 ldpath = gSystem->Getenv("DYLD_LIBRARY_PATH");
4592 if (!ldpath.IsNull())
4593 ldpath += ":";
4594 ldpath += gSystem->Getenv("LD_LIBRARY_PATH");
4595 if (!ldpath.IsNull())
4596 ldpath += ":";
4597 ldpath += gSystem->Getenv("DYLD_FALLBACK_LIBRARY_PATH");
4598#else
4599 ldpath = gSystem->Getenv("LD_LIBRARY_PATH");
4600#endif
4601 if (ldpath.IsNull())
4602 dynpath = rdynpath;
4603 else {
4604 dynpath = ldpath; dynpath += ":"; dynpath += rdynpath;
4605 }
4606 if (!dynpath.Contains(TROOT::GetLibDir())) {
4607 dynpath += ":"; dynpath += TROOT::GetLibDir();
4608 }
4609 if (gCling) {
4610 dynpath += ":"; dynpath += gCling->GetSTLIncludePath();
4611 } else
4612 initialized = kFALSE;
4613
4614#if defined(R__WINGCC) || defined(R__MACOSX)
4615 if (!dynpath.EndsWith(":")) dynpath += ":";
4616 dynpath += "/usr/local/lib:/usr/X11R6/lib:/usr/lib:/lib:";
4617 dynpath += "/lib/x86_64-linux-gnu:/usr/local/lib64:/usr/lib64:/lib64:";
4618#else
4619 // trick to get the system search path
4620 std::string cmd("LD_DEBUG=libs LD_PRELOAD=DOESNOTEXIST ls 2>&1");
4621 FILE *pf = popen(cmd.c_str (), "r");
4622 std::string result = "";
4623 char buffer[128];
4624 while (!feof(pf)) {
4625 if (fgets(buffer, 128, pf) != NULL)
4626 result += buffer;
4627 }
4628 pclose(pf);
4629 std::size_t from = result.find("search path=", result.find("(LD_LIBRARY_PATH)"));
4630 std::size_t to = result.find("(system search path)");
4631 if (from != std::string::npos && to != std::string::npos) {
4632 from += 12;
4633 std::string sys_path = result.substr(from, to-from);
4634 sys_path.erase(std::remove_if(sys_path.begin(), sys_path.end(), isspace), sys_path.end());
4635 if (!dynpath.EndsWith(":")) dynpath += ":";
4636 dynpath += sys_path.c_str();
4637 }
4638 dynpath.ReplaceAll("::", ":");
4639#endif
4640 if (gDebug > 0) std::cout << "dynpath = " << dynpath.Data() << std::endl;
4641 }
4642 return dynpath;
4643}
4644
4645////////////////////////////////////////////////////////////////////////////////
4646/// Add a new directory to the dynamic path.
4647
4648void TUnixSystem::AddDynamicPath(const char *path)
4649{
4650 if (path) {
4651 TString oldpath = DynamicPath(0, kFALSE);
4652 oldpath.Append(":");
4653 oldpath.Append(path);
4654 DynamicPath(oldpath);
4655 }
4656}
4657
4658////////////////////////////////////////////////////////////////////////////////
4659/// Return the dynamic path (used to find shared libraries).
4660
4662{
4663 return DynamicPath(0, kFALSE);
4664}
4665
4666////////////////////////////////////////////////////////////////////////////////
4667/// Set the dynamic path to a new value.
4668/// If the value of 'path' is zero, the dynamic path is reset to its
4669/// default value.
4670
4671void TUnixSystem::SetDynamicPath(const char *path)
4672{
4673 if (!path)
4674 DynamicPath(0, kTRUE);
4675 else
4676 DynamicPath(path);
4677}
4678
4679////////////////////////////////////////////////////////////////////////////////
4680/// Returns the path of a shared library (searches for library in the
4681/// shared library search path). If no file name extension is provided
4682/// it first tries .so, .sl, .dl and then .a (for AIX).
4683
4685{
4686 char buf[PATH_MAX + 1];
4687 char *res = realpath(sLib.Data(), buf);
4688 if (res) sLib = buf;
4689 TString searchFor = sLib;
4691 return sLib;
4692 }
4693 sLib = searchFor;
4694 const char* lib = sLib.Data();
4695 int len = sLib.Length();
4696 if (len > 3 && (!strcmp(lib+len-3, ".so") ||
4697 !strcmp(lib+len-3, ".dl") ||
4698 !strcmp(lib+len-4, ".dll") ||
4699 !strcmp(lib+len-4, ".DLL") ||
4700 !strcmp(lib+len-6, ".dylib") ||
4701 !strcmp(lib+len-3, ".sl") ||
4702 !strcmp(lib+len-2, ".a"))) {
4704 return sLib;
4705 }
4706 if (!quiet)
4707 Error("FindDynamicLibrary",
4708 "%s does not exist in %s", searchFor.Data(), GetDynamicPath());
4709 return 0;
4710 }
4711 static const char* exts[] = {
4712 ".so", ".dll", ".dylib", ".sl", ".dl", ".a", 0 };
4713 const char** ext = exts;
4714 while (*ext) {
4715 TString fname(sLib);
4716 fname += *ext;
4717 ++ext;
4719 sLib.Swap(fname);
4720 return sLib;
4721 }
4722 }
4723
4724 if (!quiet)
4725 Error("FindDynamicLibrary",
4726 "%s[.so | .dll | .dylib | .sl | .dl | .a] does not exist in %s",
4727 searchFor.Data(), GetDynamicPath());
4728
4729 return 0;
4730}
4731
4732//---- System, CPU and Memory info ---------------------------------------------
4733
4734#if defined(R__MACOSX)
4735#include <sys/resource.h>
4736#include <mach/mach.h>
4737#include <mach/mach_error.h>
4738
4739////////////////////////////////////////////////////////////////////////////////
4740/// Get system info for Mac OS X.
4741
4742static void GetDarwinSysInfo(SysInfo_t *sysinfo)
4743{
4744 FILE *p = gSystem->OpenPipe("sysctl -n kern.ostype hw.model hw.ncpu hw.cpufrequency "
4745 "hw.busfrequency hw.l2cachesize hw.memsize", "r");
4746 TString s;
4747 s.Gets(p);
4748 sysinfo->fOS = s;
4749 s.Gets(p);
4750 sysinfo->fModel = s;
4751 s.Gets(p);
4752 sysinfo->fCpus = s.Atoi();
4753 s.Gets(p);
4754 Long64_t t = s.Atoll();
4755 sysinfo->fCpuSpeed = Int_t(t / 1000000);
4756 s.Gets(p);
4757 t = s.Atoll();
4758 sysinfo->fBusSpeed = Int_t(t / 1000000);
4759 s.Gets(p);
4760 sysinfo->fL2Cache = s.Atoi() / 1024;
4761 s.Gets(p);
4762 t = s.Atoll();
4763 sysinfo->fPhysRam = Int_t(t / 1024 / 1024);
4764 gSystem->ClosePipe(p);
4765 p = gSystem->OpenPipe("hostinfo", "r");
4766 while (s.Gets(p)) {
4767 if (s.BeginsWith("Processor type: ")) {
4768 TPRegexp("Processor type: ([^ ]+).*").Substitute(s, "$1");
4769 sysinfo->fCpuType = s;
4770 }
4771 }
4772 gSystem->ClosePipe(p);
4773}
4774
4775////////////////////////////////////////////////////////////////////////////////
4776/// Get CPU load on Mac OS X.
4777
4778static void ReadDarwinCpu(long *ticks)
4779{
4780 mach_msg_type_number_t count;
4781 kern_return_t kr;
4782 host_cpu_load_info_data_t cpu;
4783
4784 ticks[0] = ticks[1] = ticks[2] = ticks[3] = 0;
4785
4786 count = HOST_CPU_LOAD_INFO_COUNT;
4787 kr = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&cpu, &count);
4788 if (kr != KERN_SUCCESS) {
4789 ::Error("TUnixSystem::ReadDarwinCpu", "host_statistics: %s", mach_error_string(kr));
4790 } else {
4791 ticks[0] = cpu.cpu_ticks[CPU_STATE_USER];
4792 ticks[1] = cpu.cpu_ticks[CPU_STATE_SYSTEM];
4793 ticks[2] = cpu.cpu_ticks[CPU_STATE_IDLE];
4794 ticks[3] = cpu.cpu_ticks[CPU_STATE_NICE];
4795 }
4796}
4797
4798////////////////////////////////////////////////////////////////////////////////
4799/// Get CPU stat for Mac OS X. Use sampleTime to set the interval over which
4800/// the CPU load will be measured, in ms (default 1000).
4801
4802static void GetDarwinCpuInfo(CpuInfo_t *cpuinfo, Int_t sampleTime)
4803{
4804 Double_t avg[3];
4805 if (getloadavg(avg, sizeof(avg)) < 0) {
4806 ::Error("TUnixSystem::GetDarwinCpuInfo", "getloadavg failed");
4807 } else {
4808 cpuinfo->fLoad1m = (Float_t)avg[0];
4809 cpuinfo->fLoad5m = (Float_t)avg[1];
4810 cpuinfo->fLoad15m = (Float_t)avg[2];
4811 }
4812
4813 Long_t cpu_ticks1[4], cpu_ticks2[4];
4814 ReadDarwinCpu(cpu_ticks1);
4815 gSystem->Sleep(sampleTime);
4816 ReadDarwinCpu(cpu_ticks2);
4817
4818 Long_t userticks = (cpu_ticks2[0] + cpu_ticks2[3]) -
4819 (cpu_ticks1[0] + cpu_ticks1[3]);
4820 Long_t systicks = cpu_ticks2[1] - cpu_ticks1[1];
4821 Long_t idleticks = cpu_ticks2[2] - cpu_ticks1[2];
4822 if (userticks < 0) userticks = 0;
4823 if (systicks < 0) systicks = 0;
4824 if (idleticks < 0) idleticks = 0;
4825 Long_t totalticks = userticks + systicks + idleticks;
4826 if (totalticks) {
4827 cpuinfo->fUser = ((Float_t)(100 * userticks)) / ((Float_t)totalticks);
4828 cpuinfo->fSys = ((Float_t)(100 * systicks)) / ((Float_t)totalticks);
4829 cpuinfo->fTotal = cpuinfo->fUser + cpuinfo->fSys;
4830 cpuinfo->fIdle = ((Float_t)(100 * idleticks)) / ((Float_t)totalticks);
4831 }
4832}
4833
4834////////////////////////////////////////////////////////////////////////////////
4835/// Get VM stat for Mac OS X.
4836
4837static void GetDarwinMemInfo(MemInfo_t *meminfo)
4838{
4839 static Int_t pshift = 0;
4840 static DIR *dirp;
4841 vm_statistics_data_t vm_info;
4842 mach_msg_type_number_t count;
4843 kern_return_t kr;
4844 struct dirent *dp;
4845 Long64_t total, used, free, swap_total, swap_used;
4846
4847 count = HOST_VM_INFO_COUNT;
4848 kr = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_info, &count);
4849 if (kr != KERN_SUCCESS) {
4850 ::Error("TUnixSystem::GetDarwinMemInfo", "host_statistics: %s", mach_error_string(kr));
4851 return;
4852 }
4853 if (pshift == 0) {
4854 for (int psize = getpagesize(); psize > 1; psize >>= 1)
4855 pshift++;
4856 }
4857
4858 used = (Long64_t)(vm_info.active_count + vm_info.inactive_count + vm_info.wire_count) << pshift;
4859 free = (Long64_t)(vm_info.free_count) << pshift;
4860 total = (Long64_t)(vm_info.active_count + vm_info.inactive_count + vm_info.free_count + vm_info.wire_count) << pshift;
4861
4862 // Swap is available at same time as mem, so grab values here.
4863 swap_used = vm_info.pageouts << pshift;
4864
4865 // Figure out total swap. This adds up the size of the swapfiles */
4866 dirp = opendir("/private/var/vm");
4867 if (!dirp)
4868 return;
4869
4870 swap_total = 0;
4871 while ((dp = readdir(dirp)) != 0) {
4872 struct stat sb;
4873 char fname [MAXNAMLEN];
4874 if (strncmp(dp->d_name, "swapfile", 8))
4875 continue;
4876 strlcpy(fname, "/private/var/vm/",MAXNAMLEN);
4877 strlcat (fname, dp->d_name,MAXNAMLEN);
4878 if (stat(fname, &sb) < 0)
4879 continue;
4880 swap_total += sb.st_size;
4881 }
4882 closedir(dirp);
4883
4884 meminfo->fMemTotal = (Int_t) (total >> 20); // divide by 1024 * 1024
4885 meminfo->fMemUsed = (Int_t) (used >> 20);
4886 meminfo->fMemFree = (Int_t) (free >> 20);
4887 meminfo->fSwapTotal = (Int_t) (swap_total >> 20);
4888 meminfo->fSwapUsed = (Int_t) (swap_used >> 20);
4889 meminfo->fSwapFree = meminfo->fSwapTotal - meminfo->fSwapUsed;
4890}
4891
4892////////////////////////////////////////////////////////////////////////////////
4893/// Get process info for this process on Mac OS X.
4894/// Code largely taken from:
4895/// http://www.opensource.apple.com/source/top/top-15/libtop.c
4896/// The virtual memory usage is slightly over estimated as we don't
4897/// subtract shared regions, but the value makes more sense
4898/// then pure vsize, which is useless on 64-bit machines.
4899
4900static void GetDarwinProcInfo(ProcInfo_t *procinfo)
4901{
4902#ifdef _LP64
4903#define vm_region vm_region_64
4904#endif
4905
4906// taken from <mach/shared_memory_server.h> which is obsoleted in 10.5
4907#define GLOBAL_SHARED_TEXT_SEGMENT 0x90000000U
4908#define GLOBAL_SHARED_DATA_SEGMENT 0xA0000000U
4909#define SHARED_TEXT_REGION_SIZE 0x10000000
4910#define SHARED_DATA_REGION_SIZE 0x10000000
4911
4912 struct rusage ru;
4913 if (getrusage(RUSAGE_SELF, &ru) < 0) {
4914 ::SysError("TUnixSystem::GetDarwinProcInfo", "getrusage failed");
4915 } else {
4916 procinfo->fCpuUser = (Float_t)(ru.ru_utime.tv_sec) +
4917 ((Float_t)(ru.ru_utime.tv_usec) / 1000000.);
4918 procinfo->fCpuSys = (Float_t)(ru.ru_stime.tv_sec) +
4919 ((Float_t)(ru.ru_stime.tv_usec) / 1000000.);
4920 }
4921
4922 task_basic_info_data_t ti;
4923 mach_msg_type_number_t count;
4924 kern_return_t kr;
4925
4926 task_t a_task = mach_task_self();
4927
4928 count = TASK_BASIC_INFO_COUNT;
4929 kr = task_info(a_task, TASK_BASIC_INFO, (task_info_t)&ti, &count);
4930 if (kr != KERN_SUCCESS) {
4931 ::Error("TUnixSystem::GetDarwinProcInfo", "task_info: %s", mach_error_string(kr));
4932 } else {
4933 // resident size does not require any calculation. Virtual size
4934 // needs to be adjusted if traversing memory objects do not include the
4935 // globally shared text and data regions
4936 mach_port_t object_name;
4937 vm_address_t address;
4938 vm_region_top_info_data_t info;
4939 vm_size_t vsize, vprvt, rsize, size;
4940 rsize = ti.resident_size;
4941 vsize = ti.virtual_size;
4942 vprvt = 0;
4943 for (address = 0; ; address += size) {
4944 // get memory region
4945 count = VM_REGION_TOP_INFO_COUNT;
4946 if (vm_region(a_task, &address, &size,
4947 VM_REGION_TOP_INFO, (vm_region_info_t)&info, &count,
4948 &object_name) != KERN_SUCCESS) {
4949 // no more memory regions.
4950 break;
4951 }
4952
4953 if (address >= GLOBAL_SHARED_TEXT_SEGMENT &&
4954 address < (GLOBAL_SHARED_DATA_SEGMENT + SHARED_DATA_REGION_SIZE)) {
4955 // This region is private shared.
4956 // Check if this process has the globally shared
4957 // text and data regions mapped in. If so, adjust
4958 // virtual memory size and exit loop.
4959 if (info.share_mode == SM_EMPTY) {
4960 vm_region_basic_info_data_64_t b_info;
4961 count = VM_REGION_BASIC_INFO_COUNT_64;
4962 if (vm_region_64(a_task, &address,
4963 &size, VM_REGION_BASIC_INFO,
4964 (vm_region_info_t)&b_info, &count,
4965 &object_name) != KERN_SUCCESS) {
4966 break;
4967 }
4968
4969 if (b_info.reserved) {
4970 vsize -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
4971 //break; // only for vsize
4972 }
4973 }
4974 // Short circuit the loop if this isn't a shared
4975 // private region, since that's the only region
4976 // type we care about within the current address range.
4977 if (info.share_mode != SM_PRIVATE) {
4978 continue;
4979 }
4980 }
4981 switch (info.share_mode) {
4982 case SM_COW: {
4983 if (info.ref_count == 1) {
4984 vprvt += size;
4985 } else {
4986 vprvt += info.private_pages_resident * getpagesize();
4987 }
4988 break;
4989 }
4990 case SM_PRIVATE: {
4991 vprvt += size;
4992 break;
4993 }
4994 default:
4995 break;
4996 }
4997 }
4998
4999 procinfo->fMemResident = (Long_t)(rsize / 1024);
5000 //procinfo->fMemVirtual = (Long_t)(vsize / 1024);
5001 procinfo->fMemVirtual = (Long_t)(vprvt / 1024);
5002 }
5003}
5004#endif
5005
5006#if defined(R__LINUX)
5007////////////////////////////////////////////////////////////////////////////////
5008/// Get system info for Linux. Only fBusSpeed is not set.
5009
5010static void GetLinuxSysInfo(SysInfo_t *sysinfo)
5011{
5012 TString s;
5013 FILE *f = fopen("/proc/cpuinfo", "r");
5014 if (f) {
5015 while (s.Gets(f)) {
5016 if (s.BeginsWith("model name")) {
5017 TPRegexp("^.+: *(.*$)").Substitute(s, "$1");
5018 sysinfo->fModel = s;
5019 }
5020 if (s.BeginsWith("cpu MHz")) {
5021 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5022 sysinfo->fCpuSpeed = s.Atoi();
5023 }
5024 if (s.BeginsWith("cache size")) {
5025 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5026 sysinfo->fL2Cache = s.Atoi();
5027 }
5028 if (s.BeginsWith("processor")) {
5029 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5030 sysinfo->fCpus = s.Atoi();
5031 sysinfo->fCpus++;
5032 }
5033 }
5034 fclose(f);
5035 }
5036
5037 f = fopen("/proc/meminfo", "r");
5038 if (f) {
5039 while (s.Gets(f)) {
5040 if (s.BeginsWith("MemTotal")) {
5041 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5042 sysinfo->fPhysRam = (s.Atoi() / 1024);
5043 break;
5044 }
5045 }
5046 fclose(f);
5047 }
5048
5049 f = gSystem->OpenPipe("uname -s -p", "r");
5050 if (f) {
5051 s.Gets(f);
5052 Ssiz_t from = 0;
5053 s.Tokenize(sysinfo->fOS, from);
5054 s.Tokenize(sysinfo->fCpuType, from);
5056 }
5057}
5058
5059////////////////////////////////////////////////////////////////////////////////
5060/// Get CPU load on Linux.
5061
5062static void ReadLinuxCpu(long *ticks)
5063{
5064 ticks[0] = ticks[1] = ticks[2] = ticks[3] = 0;
5065
5066 TString s;
5067 FILE *f = fopen("/proc/stat", "r");
5068 if (!f) return;
5069 s.Gets(f);
5070 // user, user nice, sys, idle
5071 sscanf(s.Data(), "%*s %ld %ld %ld %ld", &ticks[0], &ticks[3], &ticks[1], &ticks[2]);
5072 fclose(f);
5073}
5074
5075////////////////////////////////////////////////////////////////////////////////
5076/// Get CPU stat for Linux. Use sampleTime to set the interval over which
5077/// the CPU load will be measured, in ms (default 1000).
5078
5079static void GetLinuxCpuInfo(CpuInfo_t *cpuinfo, Int_t sampleTime)
5080{
5081 Double_t avg[3] = { -1., -1., -1. };
5082#ifndef R__WINGCC
5083 if (getloadavg(avg, sizeof(avg)) < 0) {
5084 ::Error("TUnixSystem::GetLinuxCpuInfo", "getloadavg failed");
5085 } else
5086#endif
5087 {
5088 cpuinfo->fLoad1m = (Float_t)avg[0];
5089 cpuinfo->fLoad5m = (Float_t)avg[1];
5090 cpuinfo->fLoad15m = (Float_t)avg[2];
5091 }
5092
5093 Long_t cpu_ticks1[4], cpu_ticks2[4];
5094 ReadLinuxCpu(cpu_ticks1);
5095 gSystem->Sleep(sampleTime);
5096 ReadLinuxCpu(cpu_ticks2);
5097
5098 Long_t userticks = (cpu_ticks2[0] + cpu_ticks2[3]) -
5099 (cpu_ticks1[0] + cpu_ticks1[3]);
5100 Long_t systicks = cpu_ticks2[1] - cpu_ticks1[1];
5101 Long_t idleticks = cpu_ticks2[2] - cpu_ticks1[2];
5102 if (userticks < 0) userticks = 0;
5103 if (systicks < 0) systicks = 0;
5104 if (idleticks < 0) idleticks = 0;
5105 Long_t totalticks = userticks + systicks + idleticks;
5106 if (totalticks) {
5107 cpuinfo->fUser = ((Float_t)(100 * userticks)) / ((Float_t)totalticks);
5108 cpuinfo->fSys = ((Float_t)(100 * systicks)) / ((Float_t)totalticks);
5109 cpuinfo->fTotal = cpuinfo->fUser + cpuinfo->fSys;
5110 cpuinfo->fIdle = ((Float_t)(100 * idleticks)) / ((Float_t)totalticks);
5111 }
5112}
5113
5114////////////////////////////////////////////////////////////////////////////////
5115/// Get VM stat for Linux.
5116
5117static void GetLinuxMemInfo(MemInfo_t *meminfo)
5118{
5119 TString s;
5120 FILE *f = fopen("/proc/meminfo", "r");
5121 if (!f) return;
5122 while (s.Gets(f)) {
5123 if (s.BeginsWith("MemTotal")) {
5124 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5125 meminfo->fMemTotal = (s.Atoi() / 1024);
5126 }
5127 if (s.BeginsWith("MemFree")) {
5128 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5129 meminfo->fMemFree = (s.Atoi() / 1024);
5130 }
5131 if (s.BeginsWith("SwapTotal")) {
5132 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5133 meminfo->fSwapTotal = (s.Atoi() / 1024);
5134 }
5135 if (s.BeginsWith("SwapFree")) {
5136 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
5137 meminfo->fSwapFree = (s.Atoi() / 1024);
5138 }
5139 }
5140 fclose(f);
5141
5142 meminfo->fMemUsed = meminfo->fMemTotal - meminfo->fMemFree;
5143 meminfo->fSwapUsed = meminfo->fSwapTotal - meminfo->fSwapFree;
5144}
5145
5146////////////////////////////////////////////////////////////////////////////////
5147/// Get process info for this process on Linux.
5148
5149static void GetLinuxProcInfo(ProcInfo_t *procinfo)
5150{
5151 struct rusage ru;
5152 if (getrusage(RUSAGE_SELF, &ru) < 0) {
5153 ::SysError("TUnixSystem::GetLinuxProcInfo", "getrusage failed");
5154 } else {
5155 procinfo->fCpuUser = (Float_t)(ru.ru_utime.tv_sec) +
5156 ((Float_t)(ru.ru_utime.tv_usec) / 1000000.);
5157 procinfo->fCpuSys = (Float_t)(ru.ru_stime.tv_sec) +
5158 ((Float_t)(ru.ru_stime.tv_usec) / 1000000.);
5159 }
5160
5161 procinfo->fMemVirtual = -1;
5162 procinfo->fMemResident = -1;
5163 TString s;
5164 FILE *f = fopen(TString::Format("/proc/%d/statm", gSystem->GetPid()), "r");
5165 if (f) {
5166 s.Gets(f);
5167 fclose(f);
5168 Long_t total, rss;
5169 sscanf(s.Data(), "%ld %ld", &total, &rss);
5170 procinfo->fMemVirtual = total * (getpagesize() / 1024);
5171 procinfo->fMemResident = rss * (getpagesize() / 1024);
5172 }
5173}
5174#endif
5175
5176////////////////////////////////////////////////////////////////////////////////
5177/// Returns static system info, like OS type, CPU type, number of CPUs
5178/// RAM size, etc into the SysInfo_t structure. Returns -1 in case of error,
5179/// 0 otherwise.
5180
5182{
5183 if (!info) return -1;
5184
5185 static SysInfo_t sysinfo;
5186
5187 if (!sysinfo.fCpus) {
5188#if defined(R__MACOSX)
5189 GetDarwinSysInfo(&sysinfo);
5190#elif defined(R__LINUX)
5191 GetLinuxSysInfo(&sysinfo);
5192#endif
5193 }
5194
5195 *info = sysinfo;
5196
5197 return 0;
5198}
5199
5200////////////////////////////////////////////////////////////////////////////////
5201/// Returns cpu load average and load info into the CpuInfo_t structure.
5202/// Returns -1 in case of error, 0 otherwise. Use sampleTime to set the
5203/// interval over which the CPU load will be measured, in ms (default 1000).
5204
5205int TUnixSystem::GetCpuInfo(CpuInfo_t *info, Int_t sampleTime) const
5206{
5207 if (!info) return -1;
5208
5209#if defined(R__MACOSX)
5210 GetDarwinCpuInfo(info, sampleTime);
5211#elif defined(R__LINUX)
5212 GetLinuxCpuInfo(info, sampleTime);
5213#endif
5214
5215 return 0;
5216}
5217
5218////////////////////////////////////////////////////////////////////////////////
5219/// Returns ram and swap memory usage info into the MemInfo_t structure.
5220/// Returns -1 in case of error, 0 otherwise.
5221
5223{
5224 if (!info) return -1;
5225
5226#if defined(R__MACOSX)
5227 GetDarwinMemInfo(info);
5228#elif defined(R__LINUX)
5229 GetLinuxMemInfo(info);
5230#endif
5231
5232 return 0;
5233}
5234
5235////////////////////////////////////////////////////////////////////////////////
5236/// Returns cpu and memory used by this process into the ProcInfo_t structure.
5237/// Returns -1 in case of error, 0 otherwise.
5238
5240{
5241 if (!info) return -1;
5242
5243#if defined(R__MACOSX)
5244 GetDarwinProcInfo(info);
5245#elif defined(R__LINUX)
5246 GetLinuxProcInfo(info);
5247#endif
5248
5249 return 0;
5250}
#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:363
R__EXTERN Int_t gDebug
Definition: Rtypes.h:90
@ kItimerResolution
Definition: Rtypes.h:59
@ kMAXSIGNALS
Definition: Rtypes.h:56
@ kMAXPATHLEN
Definition: Rtypes.h:57
R__EXTERN TApplication * gApplication
Definition: TApplication.h:165
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
#define Printf
Definition: TGeoToOCC.h:18
float * q
Definition: THbookFile.cxx:87
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:540
#define gInterpreter
Definition: TInterpreter.h:538
Binding & operator=(OUT(*fun)(void))
#define gROOT
Definition: TROOT.h:410
@ kKeepAlive
Definition: TSocket.h:41
@ kBytesToRead
Definition: TSocket.h:47
@ kReuseAddr
Definition: TSocket.h:42
@ kNoBlock
Definition: TSocket.h:44
@ kSendBuffer
Definition: TSocket.h:38
@ kNoDelay
Definition: TSocket.h:43
@ kOobInline
Definition: TSocket.h:40
@ kRecvBuffer
Definition: TSocket.h:39
@ kProcessGroup
Definition: TSocket.h:45
@ kAtMark
Definition: TSocket.h:46
@ kDontBlock
Definition: TSocket.h:54
@ kPeek
Definition: TSocket.h:53
@ kOob
Definition: TSocket.h:52
char * Form(const char *fmt,...)
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2465
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:2500
ESignals
@ kSigIllegalInstruction
@ kSigPipe
@ kSigBus
@ kSigWindowChanged
@ kSigUrgent
@ kSigUser2
@ kSigFloatingException
@ kSigChild
@ kSigAlarm
@ kSigSegmentationViolation
@ kSigSystem
R__EXTERN const char * gProgName
Definition: TSystem.h:224
R__EXTERN TVirtualMutex * gSystemMutex
Definition: TSystem.h:226
typedef void((*Func_t)())
R__EXTERN const char * gRootDir
Definition: TSystem.h:223
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:540
@ 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:541
R__EXTERN const char * gProgPath
Definition: TSystem.h:225
#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:136
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:150
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:165
Collectable string class.
Definition: TObjString.h:28
TString & String()
Definition: TObjString.h:49
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 const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition: TROOT.cxx:3010
static const TString & GetLibDir()
Get the library directory in the installation. Static utility function.
Definition: TROOT.cxx:2968
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:2152
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1081
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:2172
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:2286
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2264
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:248
virtual void Unload(const char *module)
Unload a shared library.
Definition: TSystem.cxx:2052
TSeqCollection * fFileHandler
Definition: TSystem.h:278
Int_t fMaxrfd
Definition: TSystem.h:263
virtual void AddFileHandler(TFileHandler *fh)
Add a file handler to the list of system file handlers.
Definition: TSystem.cxx:563
TString & GetLastErrorString()
Return the thread local storage for the custom last error message.
Definition: TSystem.cxx:2110
virtual Func_t DynFindSymbol(const char *module, const char *entry)
Find specific entry point in specified library.
Definition: TSystem.cxx:2044
Bool_t fInsideNotify
Definition: TSystem.h:268
static void ResetErrno()
Static function resetting system error number.
Definition: TSystem.cxx:285
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1264
static Int_t GetErrno()
Static function returning system error number.
Definition: TSystem.cxx:269
@ kDefault
Definition: TSystem.h:251
TFdSet * fReadmask
Definition: TSystem.h:257
TString fWdpath
Definition: TSystem.h:266
virtual const char * DirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:1013
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition: TSystem.cxx:852
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition: TSystem.cxx:843
virtual int GetPid()
Get process id.
Definition: TSystem.cxx:716
TString fHostname
Definition: TSystem.h:267
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:503
virtual int SetSockOpt(int sock, int kind, int val)
Set socket option.
Definition: TSystem.cxx:2479
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1652
TFdSet * fWritemask
Files that should be checked for read events.
Definition: TSystem.h:258
TFdSet * fSignals
Files with writes waiting.
Definition: TSystem.h:261
virtual char * ConcatFileName(const char *dir, const char *name)
Concatenate a directory and a file name. User must delete returned string.
Definition: TSystem.cxx:1061
virtual Bool_t IsPathLocal(const char *path)
Returns TRUE if the url in 'path' points to the local file system.
Definition: TSystem.cxx:1295
virtual const char * FindFile(const char *search, TString &file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1526
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
Make a file system directory.
Definition: TSystem.cxx:913
virtual int MakeDirectory(const char *name)
Make a directory.
Definition: TSystem.cxx:834
virtual const char * ExpandFileName(const char *fname)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1088
virtual TFileHandler * RemoveFileHandler(TFileHandler *fh)
Remove a file handler from the list of file handlers.
Definition: TSystem.cxx:573
Int_t fSigcnt
Definition: TSystem.h:265
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition: TSystem.cxx:1843
virtual void ListLibraries(const char *regexp="")
List all loaded shared libraries.
Definition: TSystem.cxx:2073
virtual FILE * OpenPipe(const char *command, const char *mode)
Open a pipe.
Definition: TSystem.cxx:671
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:1388
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition: TSystem.cxx:1071
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:1286
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:860
virtual Bool_t Init()
Initialize the OS interface.
Definition: TSystem.cxx:191
virtual void AddTimer(TTimer *t)
Add timer to list of system timers.
Definition: TSystem.cxx:480
TFdSet * fWriteready
Files with reads waiting.
Definition: TSystem.h:260
virtual int ClosePipe(FILE *pipe)
Close the pipe.
Definition: TSystem.cxx:680
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:941
virtual void AddSignalHandler(TSignalHandler *sh)
Add a signal handler to list of system signal handlers.
Definition: TSystem.cxx:541
TSeqCollection * fSignalHandler
Definition: TSystem.h:277
TFdSet * fReadready
Files that should be checked for write events.
Definition: TSystem.h:259
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:753
Int_t fNfd
Signals that were trapped.
Definition: TSystem.h:262
static const char * StripOffProto(const char *path, const char *proto)
Definition: TSystem.h:315
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition: TSystem.cxx:446
Int_t fMaxwfd
Definition: TSystem.h:264
virtual const char * WorkingDirectory()
Return working directory.
Definition: TSystem.cxx:878
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1536
virtual TInetAddress GetHostByName(const char *server)
Get Internet Protocol (IP) address of host.
Definition: TSystem.cxx:2334
virtual TSignalHandler * RemoveSignalHandler(TSignalHandler *sh)
Remove a signal handler from list of signal handlers.
Definition: TSystem.cxx:551
virtual void Setenv(const char *name, const char *value)
Set environment variable.
Definition: TSystem.cxx:1636
virtual TTimer * RemoveTimer(TTimer *t)
Remove timer from list of system timers.
Definition: TSystem.cxx:490
virtual int Unlink(const char *name)
Unlink, i.e.
Definition: TSystem.cxx:1371
TSeqCollection * fTimers
Definition: TSystem.h:276
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
static constexpr double ms
static constexpr double s
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
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