00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "RConfigure.h"
00021 #include "RConfig.h"
00022 #include "TUnixSystem.h"
00023 #include "TROOT.h"
00024 #include "TError.h"
00025 #include "TOrdCollection.h"
00026 #include "TRegexp.h"
00027 #include "TPRegexp.h"
00028 #include "TException.h"
00029 #include "Demangle.h"
00030 #include "TEnv.h"
00031 #include "TSocket.h"
00032 #include "Getline.h"
00033 #include "TInterpreter.h"
00034 #include "TApplication.h"
00035 #include "TObjString.h"
00036 #include "Riostream.h"
00037 #include "TVirtualMutex.h"
00038 #include "TObjArray.h"
00039 #include <map>
00040
00041
00042
00043 #include <unistd.h>
00044 #include <stdlib.h>
00045 #include <sys/types.h>
00046 #if defined(R__SUN) || defined(R__SGI) || defined(R__HPUX) || \
00047 defined(R__AIX) || defined(R__LINUX) || defined(R__SOLARIS) || \
00048 defined(R__ALPHA) || defined(R__HIUX) || defined(R__FBSD) || \
00049 defined(R__OBSD) || defined(R__MACOSX) || defined(R__HURD)
00050 #define HAS_DIRENT
00051 #endif
00052 #ifdef HAS_DIRENT
00053 # include <dirent.h>
00054 #else
00055 # include <sys/dir.h>
00056 #endif
00057 #if defined(ULTRIX) || defined(R__SUN)
00058 # include <sgtty.h>
00059 #endif
00060 #if defined(R__AIX) || defined(R__LINUX) || defined(R__ALPHA) || \
00061 defined(R__SGI) || defined(R__HIUX) || defined(R__FBSD) || \
00062 defined(R__OBSD) || defined(R__LYNXOS) || defined(R__MACOSX) || \
00063 defined(R__HURD)
00064 # include <sys/ioctl.h>
00065 #endif
00066 #if defined(R__AIX) || defined(R__SOLARIS)
00067 # include <sys/select.h>
00068 #endif
00069 #if defined(R__LINUX) || defined(R__HURD)
00070 # ifndef SIGSYS
00071 # define SIGSYS SIGUNUSED // SIGSYS does not exist in linux ??
00072 # endif
00073 #endif
00074 #if defined(R__ALPHA)
00075 # include <sys/mount.h>
00076 # ifndef R__TRUE64
00077 extern "C" int statfs(const char *file, struct statfs *buffer);
00078 # endif
00079 #elif defined(R__MACOSX)
00080 # include <mach-o/dyld.h>
00081 # include <sys/mount.h>
00082 extern "C" int statfs(const char *file, struct statfs *buffer);
00083 #elif defined(R__LINUX) || defined(R__HPUX) || defined(R__HURD)
00084 # include <sys/vfs.h>
00085 #elif defined(R__FBSD) || defined(R__OBSD)
00086 # include <sys/param.h>
00087 # include <sys/mount.h>
00088 #else
00089 # include <sys/statfs.h>
00090 #endif
00091
00092 #include <utime.h>
00093 #include <syslog.h>
00094 #include <sys/stat.h>
00095 #include <setjmp.h>
00096 #include <signal.h>
00097 #include <sys/param.h>
00098 #include <pwd.h>
00099 #include <grp.h>
00100 #include <errno.h>
00101 #include <sys/wait.h>
00102 #include <time.h>
00103 #include <sys/time.h>
00104 #include <sys/file.h>
00105 #include <sys/socket.h>
00106 #include <netinet/in.h>
00107 #include <netinet/tcp.h>
00108 #if defined(R__AIX)
00109 # define _XOPEN_EXTENDED_SOURCE
00110 # include <arpa/inet.h>
00111 # undef _XOPEN_EXTENDED_SOURCE
00112 # if !defined(_AIX41) && !defined(_AIX43)
00113
00114 # define HASNOT_INETATON
00115 # endif
00116 #else
00117 # include <arpa/inet.h>
00118 #endif
00119 #include <sys/un.h>
00120 #include <netdb.h>
00121 #include <fcntl.h>
00122 #if defined(R__SGI)
00123 # include <net/soioctl.h>
00124 #endif
00125 #if defined(R__SOLARIS)
00126 # include <sys/systeminfo.h>
00127 # include <sys/filio.h>
00128 # include <sys/sockio.h>
00129 # define HASNOT_INETATON
00130 # ifndef INADDR_NONE
00131 # define INADDR_NONE (UInt_t)-1
00132 # endif
00133 #endif
00134 #if defined(R__HPUX)
00135 # include <symlink.h>
00136 # include <dl.h>
00137 # if defined(R__GNU)
00138 extern "C" {
00139 extern shl_t cxxshl_load(const char *path, int flags, long address);
00140 extern int cxxshl_unload(shl_t handle);
00141 }
00142 # elif !defined(__STDCPP__)
00143 # include <cxxdl.h>
00144 # endif
00145 # if defined(hpux9)
00146 extern "C" {
00147 extern void openlog(const char *, int, int);
00148 extern void syslog(int, const char *, ...);
00149 extern void closelog(void);
00150 extern int setlogmask(int);
00151 }
00152 # define HASNOT_INETATON
00153 # endif
00154 #endif
00155 #if defined(R__ALPHA) && !defined(R__GNU)
00156 # define HASNOT_INETATON
00157 #endif
00158 #if defined(R__HIUX)
00159 # define HASNOT_INETATON
00160 #endif
00161
00162 #if defined(R__SGI) || defined(R__SOLARIS)
00163 # define HAVE_UTMPX_H
00164 # define UTMP_NO_ADDR
00165 #endif
00166
00167 #if defined(MAC_OS_X_VERSION_10_5)
00168 # define HAVE_UTMPX_H
00169 # define UTMP_NO_ADDR
00170 # ifndef ut_user
00171 # define ut_user ut_name
00172 # endif
00173 #endif
00174
00175 #if defined(R__ALPHA) || defined(R__AIX) || defined(R__FBSD) || \
00176 defined(R__OBSD) || defined(R__LYNXOS) || \
00177 (defined(R__MACOSX) && !defined(MAC_OS_X_VERSION_10_5))
00178 # define UTMP_NO_ADDR
00179 #endif
00180
00181 #if (defined(R__AIX) && !defined(_AIX43)) || \
00182 (defined(R__SUNGCC3) && !defined(__arch64__))
00183 # define USE_SIZE_T
00184 #elif defined(R__GLIBC) || defined(R__FBSD) || \
00185 (defined(R__SUNGCC3) && defined(__arch64__)) || \
00186 defined(R__OBSD) || defined(MAC_OS_X_VERSION_10_4) || \
00187 (defined(R__AIX) && defined(_AIX43))
00188 # define USE_SOCKLEN_T
00189 #endif
00190
00191 #if defined(R__LYNXOS)
00192 extern "C" {
00193 extern int putenv(const char *);
00194 extern int inet_aton(const char *, struct in_addr *);
00195 };
00196 #endif
00197
00198 #ifdef HAVE_UTMPX_H
00199 #include <utmpx.h>
00200 #define STRUCT_UTMP struct utmpx
00201 #else
00202 #include <utmp.h>
00203 #define STRUCT_UTMP struct utmp
00204 #endif
00205 #if !defined(UTMP_FILE) && defined(_PATH_UTMP) // 4.4BSD
00206 #define UTMP_FILE _PATH_UTMP
00207 #endif
00208 #if defined(UTMPX_FILE) // Solaris, SysVr4
00209 #undef UTMP_FILE
00210 #define UTMP_FILE UTMPX_FILE
00211 #endif
00212 #ifndef UTMP_FILE
00213 #define UTMP_FILE "/etc/utmp"
00214 #endif
00215
00216
00217 #if defined(R__HPUX) && !defined(R__GNU)
00218 # define HAVE_U_STACK_TRACE
00219 #endif
00220 #if defined(R__AIX)
00221
00222 #endif
00223 #if (defined(R__LINUX) || defined(R__HURD)) && !defined(R__WINGCC)
00224 # if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 1
00225 # define HAVE_BACKTRACE_SYMBOLS_FD
00226 # endif
00227 # define HAVE_DLADDR
00228 #endif
00229 #if defined(R__MACOSX)
00230 # define USE_GDB_STACK_TRACE
00231 #endif
00232
00233 #ifdef HAVE_U_STACK_TRACE
00234
00235 extern "C" void U_STACK_TRACE(void);
00236 #endif
00237 #ifdef HAVE_XL_TRBK
00238
00239 extern "C" void xl__trbk(void);
00240 #endif
00241 #ifdef HAVE_BACKTRACE_SYMBOLS_FD
00242 # include <execinfo.h>
00243 #endif
00244 #ifdef HAVE_DLADDR
00245 # ifndef __USE_GNU
00246 # define __USE_GNU
00247 # endif
00248 # include <dlfcn.h>
00249 #endif
00250
00251 #ifdef HAVE_BACKTRACE_SYMBOLS_FD
00252
00253
00254 static const int kMAX_BACKTRACE_DEPTH = 128;
00255 #endif
00256
00257
00258 #if (defined(R__LINUX) && !defined(R__WINGCC))
00259 #include <fpu_control.h>
00260 #include <fenv.h>
00261 #endif
00262
00263 #if defined(R__MACOSX) && !defined(__xlC__) && !defined(__i386__) && \
00264 !defined(__x86_64__) && !defined(__arm__)
00265 #include <fenv.h>
00266 #include <signal.h>
00267 #include <ucontext.h>
00268 #include <stdlib.h>
00269 #include <stdio.h>
00270 #include <mach/thread_status.h>
00271
00272 #define fegetenvd(x) asm volatile("mffs %0" : "=f" (x));
00273 #define fesetenvd(x) asm volatile("mtfsf 255,%0" : : "f" (x));
00274
00275 enum {
00276 FE_ENABLE_INEXACT = 0x00000008,
00277 FE_ENABLE_DIVBYZERO = 0x00000010,
00278 FE_ENABLE_UNDERFLOW = 0x00000020,
00279 FE_ENABLE_OVERFLOW = 0x00000040,
00280 FE_ENABLE_INVALID = 0x00000080,
00281 FE_ENABLE_ALL_EXCEPT = 0x000000F8
00282 };
00283 #endif
00284
00285 #if defined(R__MACOSX) && (defined(__i386__) || defined(__x86_64__) || defined(__arm__))
00286 #include <fenv.h>
00287 #endif
00288
00289
00290
00291 static STRUCT_UTMP *gUtmpContents;
00292
00293
00294 const char *kServerPath = "/tmp";
00295 const char *kProtocolName = "tcp";
00296
00297
00298 #ifndef HOWMANY
00299 # define HOWMANY(x, y) (((x)+((y)-1))/(y))
00300 #endif
00301
00302 const Int_t kNFDBITS = (sizeof(Long_t) * 8);
00303 #ifdef FD_SETSIZE
00304 const Int_t kFDSETSIZE = FD_SETSIZE;
00305 #else
00306 const Int_t kFDSETSIZE = 256;
00307 #endif
00308
00309
00310 class TFdSet {
00311 private:
00312 ULong_t fds_bits[HOWMANY(kFDSETSIZE, kNFDBITS)];
00313 public:
00314 TFdSet() { memset(fds_bits, 0, sizeof(fds_bits)); }
00315 TFdSet(const TFdSet &org) { memcpy(fds_bits, org.fds_bits, sizeof(org.fds_bits)); }
00316 TFdSet &operator=(const TFdSet &rhs) { if (this != &rhs) { memcpy(fds_bits, rhs.fds_bits, sizeof(rhs.fds_bits));} return *this; }
00317 void Zero() { memset(fds_bits, 0, sizeof(fds_bits)); }
00318 void Set(Int_t n)
00319 {
00320 if (n >= 0 && n < kFDSETSIZE) {
00321 fds_bits[n/kNFDBITS] |= (1UL << (n % kNFDBITS));
00322 } else {
00323 ::Fatal("TFdSet::Set","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1);
00324 }
00325 }
00326 void Clr(Int_t n)
00327 {
00328 if (n >= 0 && n < kFDSETSIZE) {
00329 fds_bits[n/kNFDBITS] &= ~(1UL << (n % kNFDBITS));
00330 } else {
00331 ::Fatal("TFdSet::Clr","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1);
00332 }
00333 }
00334 Int_t IsSet(Int_t n)
00335 {
00336 if (n >= 0 && n < kFDSETSIZE) {
00337 return (fds_bits[n/kNFDBITS] & (1UL << (n % kNFDBITS))) != 0;
00338 } else {
00339 ::Fatal("TFdSet::IsSet","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1);
00340 return 0;
00341 }
00342 }
00343 ULong_t *GetBits() { return (ULong_t *)fds_bits; }
00344 };
00345
00346
00347 static void SigHandler(ESignals sig)
00348 {
00349
00350
00351 if (gSystem)
00352 ((TUnixSystem*)gSystem)->DispatchSignals(sig);
00353 }
00354
00355
00356 static const char *GetExePath()
00357 {
00358 static TString exepath;
00359 if (exepath == "") {
00360 #ifdef __APPLE__
00361 exepath = _dyld_get_image_name(0);
00362 #endif
00363 #ifdef __linux
00364 char linkname[64];
00365 char buf[kMAXPATHLEN];
00366 pid_t pid;
00367
00368
00369 pid = getpid();
00370 snprintf(linkname,64, "/proc/%i/exe", pid);
00371 int ret = readlink(linkname, buf, kMAXPATHLEN);
00372 if (ret > 0 && ret < kMAXPATHLEN) {
00373 buf[ret] = 0;
00374 exepath = buf;
00375 }
00376 #endif
00377 }
00378 return exepath;
00379 }
00380
00381 #if defined(HAVE_DLADDR)
00382
00383 static void SetRootSys()
00384 {
00385 #ifndef ROOTPREFIX
00386 void *addr = (void *)SetRootSys;
00387 Dl_info info;
00388 if (dladdr(addr, &info) && info.dli_fname && info.dli_fname[0]) {
00389 char respath[kMAXPATHLEN];
00390 if (!realpath(info.dli_fname, respath)) {
00391 if (!gSystem->Getenv("ROOTSYS"))
00392 ::SysError("TUnixSystem::SetRootSys", "error getting realpath of libCore, please set ROOTSYS in the shell");
00393 } else {
00394 TString rs = gSystem->DirName(respath);
00395 gSystem->Setenv("ROOTSYS", gSystem->DirName(rs));
00396 }
00397 }
00398 #else
00399 return;
00400 #endif
00401 }
00402 #endif
00403
00404 #if defined(R__MACOSX)
00405 static TString gLinkedDylibs;
00406
00407
00408 static void DylibAdded(const struct mach_header *mh, intptr_t )
00409 {
00410 static int i = 0;
00411 static Bool_t gotFirstSo = kFALSE;
00412 static TString linkedDylibs;
00413
00414
00415
00416 if (!mh) {
00417 gLinkedDylibs = linkedDylibs;
00418 return;
00419 }
00420
00421 TString lib = _dyld_get_image_name(i++);
00422
00423 #ifndef ROOTPREFIX
00424 #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
00425
00426 if (i == 1) {
00427 char respath[kMAXPATHLEN];
00428 if (!realpath(lib, respath)) {
00429 if (!gSystem->Getenv("ROOTSYS"))
00430 ::SysError("TUnixSystem::DylibAdded", "error getting realpath of %s", gSystem->BaseName(lib));
00431 } else {
00432 TString rs = gSystem->DirName(respath);
00433 rs.ReplaceAll(" ", "\\ ");
00434 gSystem->Setenv("ROOTSYS", rs);
00435 }
00436 }
00437 #else
00438 if (lib.EndsWith("libCore.dylib") || lib.EndsWith("libCore.so")) {
00439 char respath[kMAXPATHLEN];
00440 if (!realpath(lib, respath)) {
00441 if (!gSystem->Getenv("ROOTSYS"))
00442 ::SysError("TUnixSystem::DylibAdded", "error getting realpath of libCore, please set ROOTSYS in the shell");
00443 } else {
00444 TString rs = gSystem->DirName(respath);
00445 gSystem->Setenv("ROOTSYS", gSystem->DirName(rs));
00446 }
00447 }
00448 #endif
00449 #endif
00450
00451
00452
00453
00454
00455 if (lib.EndsWith("/libSystem.B.dylib"))
00456 gotFirstSo = kTRUE;
00457
00458
00459 if (!gotFirstSo && (lib.EndsWith(".dylib") || lib.EndsWith(".so"))) {
00460 if (linkedDylibs.Length())
00461 linkedDylibs += " ";
00462 linkedDylibs += lib;
00463 }
00464 }
00465 #endif
00466
00467
00468 ClassImp(TUnixSystem)
00469
00470
00471 TUnixSystem::TUnixSystem() : TSystem("Unix", "Unix System")
00472 { }
00473
00474
00475 TUnixSystem::~TUnixSystem()
00476 {
00477
00478
00479 UnixResetSignals();
00480
00481 delete fReadmask;
00482 delete fWritemask;
00483 delete fReadready;
00484 delete fWriteready;
00485 delete fSignals;
00486 }
00487
00488
00489 Bool_t TUnixSystem::Init()
00490 {
00491
00492
00493 if (TSystem::Init())
00494 return kTRUE;
00495
00496 fReadmask = new TFdSet;
00497 fWritemask = new TFdSet;
00498 fReadready = new TFdSet;
00499 fWriteready = new TFdSet;
00500 fSignals = new TFdSet;
00501
00502
00503 UnixSignal(kSigChild, SigHandler);
00504 UnixSignal(kSigBus, SigHandler);
00505 UnixSignal(kSigSegmentationViolation, SigHandler);
00506 UnixSignal(kSigIllegalInstruction, SigHandler);
00507 UnixSignal(kSigSystem, SigHandler);
00508 UnixSignal(kSigPipe, SigHandler);
00509 UnixSignal(kSigAlarm, SigHandler);
00510 UnixSignal(kSigUrgent, SigHandler);
00511 UnixSignal(kSigFloatingException, SigHandler);
00512 UnixSignal(kSigWindowChanged, SigHandler);
00513
00514 #if defined(R__MACOSX)
00515
00516
00517 _dyld_register_func_for_add_image(DylibAdded);
00518 #elif defined(HAVE_DLADDR)
00519 SetRootSys();
00520 #endif
00521
00522 #ifndef ROOTPREFIX
00523 gRootDir = Getenv("ROOTSYS");
00524 if (gRootDir == 0)
00525 gRootDir= "/usr/local/root";
00526 #else
00527 gRootDir = ROOTPREFIX;
00528 #endif
00529
00530 return kFALSE;
00531 }
00532
00533
00534
00535
00536 void TUnixSystem::SetProgname(const char *name)
00537 {
00538
00539
00540
00541
00542
00543 if (gProgName)
00544 delete [] gProgName;
00545 if (gProgPath)
00546 delete [] gProgPath;
00547
00548 if (!name || !*name) {
00549 name = GetExePath();
00550 gProgName = StrDup(BaseName(name));
00551 gProgPath = StrDup(DirName(name));
00552 } else {
00553 gProgName = StrDup(BaseName(name));
00554 char *w = Which(Getenv("PATH"), gProgName);
00555 gProgPath = StrDup(DirName(w));
00556 delete [] w;
00557 }
00558 }
00559
00560
00561 void TUnixSystem::SetDisplay()
00562 {
00563
00564
00565 if (!Getenv("DISPLAY")) {
00566 char *tty = ::ttyname(0);
00567 if (tty) {
00568 tty += 5;
00569
00570 R__LOCKGUARD2(gSystemMutex);
00571
00572 STRUCT_UTMP *utmp_entry = (STRUCT_UTMP *)SearchUtmpEntry(ReadUtmpFile(), tty);
00573 if (utmp_entry) {
00574 if (utmp_entry->ut_host[0])
00575 if (strchr(utmp_entry->ut_host, ':')) {
00576 Setenv("DISPLAY", utmp_entry->ut_host);
00577 Warning("SetDisplay", "DISPLAY not set, setting it to %s",
00578 utmp_entry->ut_host);
00579 } else {
00580 char disp[64];
00581 snprintf(disp, sizeof(disp), "%s:0.0", utmp_entry->ut_host);
00582 Setenv("DISPLAY", disp);
00583 Warning("SetDisplay", "DISPLAY not set, setting it to %s",
00584 disp);
00585 }
00586 #ifndef UTMP_NO_ADDR
00587 else if (utmp_entry->ut_addr) {
00588 struct hostent *he;
00589 if ((he = gethostbyaddr((const char*)&utmp_entry->ut_addr,
00590 sizeof(utmp_entry->ut_addr), AF_INET))) {
00591 char disp[64];
00592 snprintf(disp, sizeof(disp), "%s:0.0", he->h_name);
00593 Setenv("DISPLAY", disp);
00594 Warning("SetDisplay", "DISPLAY not set, setting it to %s",
00595 disp);
00596 }
00597 }
00598 #endif
00599 }
00600 free(gUtmpContents);
00601 }
00602 }
00603 }
00604
00605
00606 const char *TUnixSystem::GetError()
00607 {
00608
00609
00610 Int_t err = GetErrno();
00611 if (err == 0 && fLastErrorString != "")
00612 return fLastErrorString;
00613 #if defined(R__SOLARIS) || defined (R__LINUX) || defined(R__AIX) || \
00614 defined(R__FBSD) || defined(R__OBSD) || defined(R__HURD)
00615 return strerror(err);
00616 #else
00617 if (err < 0 || err >= sys_nerr)
00618 return Form("errno out of range %d", err);
00619 return sys_errlist[err];
00620 #endif
00621 }
00622
00623
00624 const char *TUnixSystem::HostName()
00625 {
00626
00627
00628 if (fHostname == "") {
00629 char hn[64];
00630 #if defined(R__SOLARIS)
00631 sysinfo(SI_HOSTNAME, hn, sizeof(hn));
00632 #else
00633 gethostname(hn, sizeof(hn));
00634 #endif
00635 fHostname = hn;
00636 }
00637 return (const char *)fHostname;
00638 }
00639
00640
00641
00642
00643 void TUnixSystem::AddFileHandler(TFileHandler *h)
00644 {
00645
00646
00647
00648 R__LOCKGUARD2(gSystemMutex);
00649
00650 TSystem::AddFileHandler(h);
00651 if (h) {
00652 int fd = h->GetFd();
00653 if (h->HasReadInterest()) {
00654 fReadmask->Set(fd);
00655 fMaxrfd = TMath::Max(fMaxrfd, fd);
00656 }
00657 if (h->HasWriteInterest()) {
00658 fWritemask->Set(fd);
00659 fMaxwfd = TMath::Max(fMaxwfd, fd);
00660 }
00661 }
00662 }
00663
00664
00665 TFileHandler *TUnixSystem::RemoveFileHandler(TFileHandler *h)
00666 {
00667
00668
00669
00670 if (!h) return 0;
00671
00672 R__LOCKGUARD2(gSystemMutex);
00673
00674 TFileHandler *oh = TSystem::RemoveFileHandler(h);
00675 if (oh) {
00676 TFileHandler *th;
00677 TIter next(fFileHandler);
00678 fMaxrfd = -1;
00679 fMaxwfd = -1;
00680 fReadmask->Zero();
00681 fWritemask->Zero();
00682 while ((th = (TFileHandler *) next())) {
00683 int fd = th->GetFd();
00684 if (th->HasReadInterest()) {
00685 fReadmask->Set(fd);
00686 fMaxrfd = TMath::Max(fMaxrfd, fd);
00687 }
00688 if (th->HasWriteInterest()) {
00689 fWritemask->Set(fd);
00690 fMaxwfd = TMath::Max(fMaxwfd, fd);
00691 }
00692 }
00693 }
00694 return oh;
00695 }
00696
00697
00698 void TUnixSystem::AddSignalHandler(TSignalHandler *h)
00699 {
00700
00701
00702
00703 R__LOCKGUARD2(gSystemMutex);
00704
00705 TSystem::AddSignalHandler(h);
00706 UnixSignal(h->GetSignal(), SigHandler);
00707 }
00708
00709
00710 TSignalHandler *TUnixSystem::RemoveSignalHandler(TSignalHandler *h)
00711 {
00712
00713
00714
00715 if (!h) return 0;
00716
00717 R__LOCKGUARD2(gSystemMutex);
00718
00719 TSignalHandler *oh = TSystem::RemoveSignalHandler(h);
00720
00721 Bool_t last = kTRUE;
00722 TSignalHandler *hs;
00723 TIter next(fSignalHandler);
00724
00725 while ((hs = (TSignalHandler*) next())) {
00726 if (hs->GetSignal() == h->GetSignal())
00727 last = kFALSE;
00728 }
00729 if (last)
00730 ResetSignal(h->GetSignal(), kTRUE);
00731
00732 return oh;
00733 }
00734
00735
00736 void TUnixSystem::ResetSignal(ESignals sig, Bool_t reset)
00737 {
00738
00739
00740
00741 if (reset)
00742 UnixResetSignal(sig);
00743 else
00744 UnixSignal(sig, SigHandler);
00745 }
00746
00747
00748 void TUnixSystem::IgnoreSignal(ESignals sig, Bool_t ignore)
00749 {
00750
00751
00752
00753 UnixIgnoreSignal(sig, ignore);
00754 }
00755
00756
00757 void TUnixSystem::SigAlarmInterruptsSyscalls(Bool_t set)
00758 {
00759
00760
00761
00762
00763
00764
00765
00766 UnixSigAlarmInterruptsSyscalls(set);
00767 }
00768
00769
00770 Int_t TUnixSystem::GetFPEMask()
00771 {
00772
00773
00774 Int_t mask = 0;
00775
00776 #if defined(R__LINUX) && !defined(__powerpc__)
00777 #if defined(__GLIBC__) && (__GLIBC__>2 || __GLIBC__==2 && __GLIBC_MINOR__>=1)
00778
00779 #if __GLIBC_MINOR__>=3
00780
00781
00782 feclearexcept(FE_ALL_EXCEPT);
00783 Int_t oldmask = feenableexcept(0);
00784
00785 #else
00786 fenv_t oldenv;
00787 fegetenv(&oldenv);
00788 fesetenv(&oldenv);
00789 #ifdef __alpha__
00790 ULong_t oldmask = ~oldenv;
00791 #elif __ia64__
00792 Int_t oldmask = ~oldenv;
00793 #else
00794 Int_t oldmask = ~oldenv.__control_word;
00795 #endif
00796 #endif
00797
00798 if (oldmask & FE_INVALID ) mask |= kInvalid;
00799 if (oldmask & FE_DIVBYZERO) mask |= kDivByZero;
00800 if (oldmask & FE_OVERFLOW ) mask |= kOverflow;
00801 if (oldmask & FE_UNDERFLOW) mask |= kUnderflow;
00802 # ifdef FE_INEXACT
00803 if (oldmask & FE_INEXACT ) mask |= kInexact;
00804 # endif
00805 #endif
00806 #endif
00807
00808 #if defined(R__MACOSX) && (defined(__i386__) || defined(__x86_64__) || defined(__arm__))
00809 fenv_t oldenv;
00810 fegetenv(&oldenv);
00811 fesetenv(&oldenv);
00812 #if defined(__arm__)
00813 Int_t oldmask = ~oldenv.__fpscr;
00814 #else
00815 Int_t oldmask = ~oldenv.__control;
00816 #endif
00817
00818 if (oldmask & FE_INVALID ) mask |= kInvalid;
00819 if (oldmask & FE_DIVBYZERO) mask |= kDivByZero;
00820 if (oldmask & FE_OVERFLOW ) mask |= kOverflow;
00821 if (oldmask & FE_UNDERFLOW) mask |= kUnderflow;
00822 # ifdef FE_INEXACT
00823 if (oldmask & FE_INEXACT ) mask |= kInexact;
00824 # endif
00825 #endif
00826
00827 #if defined(R__MACOSX) && !defined(__xlC__) && !defined(__i386__) && \
00828 !defined(__x86_64__) && !defined(__arm__)
00829 Long64_t oldmask;
00830 fegetenvd(oldmask);
00831
00832 if (oldmask & FE_ENABLE_INVALID ) mask |= kInvalid;
00833 if (oldmask & FE_ENABLE_DIVBYZERO) mask |= kDivByZero;
00834 if (oldmask & FE_ENABLE_OVERFLOW ) mask |= kOverflow;
00835 if (oldmask & FE_ENABLE_UNDERFLOW) mask |= kUnderflow;
00836 if (oldmask & FE_ENABLE_INEXACT ) mask |= kInexact;
00837 #endif
00838
00839 return mask;
00840 }
00841
00842
00843 Int_t TUnixSystem::SetFPEMask(Int_t mask)
00844 {
00845
00846
00847
00848 if (mask) { }
00849
00850 Int_t old = GetFPEMask();
00851
00852 #if defined(R__LINUX) && !defined(__powerpc__)
00853 #if defined(__GLIBC__) && (__GLIBC__>2 || __GLIBC__==2 && __GLIBC_MINOR__>=1)
00854 Int_t newm = 0;
00855 if (mask & kInvalid ) newm |= FE_INVALID;
00856 if (mask & kDivByZero) newm |= FE_DIVBYZERO;
00857 if (mask & kOverflow ) newm |= FE_OVERFLOW;
00858 if (mask & kUnderflow) newm |= FE_UNDERFLOW;
00859 # ifdef FE_INEXACT
00860 if (mask & kInexact ) newm |= FE_INEXACT;
00861 # endif
00862
00863 #if __GLIBC_MINOR__>=3
00864
00865
00866 feclearexcept(FE_ALL_EXCEPT);
00867 fedisableexcept(FE_ALL_EXCEPT);
00868 feenableexcept(newm);
00869
00870 #else
00871
00872 fenv_t cur;
00873 fegetenv(&cur);
00874 #if defined __ia64__ || defined __alpha__
00875 cur &= ~newm;
00876 #else
00877 cur.__control_word &= ~newm;
00878 #endif
00879 fesetenv(&cur);
00880
00881 #endif
00882 #endif
00883 #endif
00884
00885 #if defined(R__MACOSX) && (defined(__i386__) || defined(__x86_64__) || defined(__arm__))
00886 Int_t newm = 0;
00887 if (mask & kInvalid ) newm |= FE_INVALID;
00888 if (mask & kDivByZero) newm |= FE_DIVBYZERO;
00889 if (mask & kOverflow ) newm |= FE_OVERFLOW;
00890 if (mask & kUnderflow) newm |= FE_UNDERFLOW;
00891 if (mask & kInexact ) newm |= FE_INEXACT;
00892
00893 fenv_t cur;
00894 fegetenv(&cur);
00895 #if defined(__arm__)
00896 cur.__fpscr &= ~newm;
00897 #else
00898 cur.__control &= ~newm;
00899 #endif
00900 fesetenv(&cur);
00901 #endif
00902
00903 #if defined(R__MACOSX) && !defined(__xlC__) && !defined(__i386__) && \
00904 !defined(__x86_64__) && !defined(__arm__)
00905 Int_t newm = 0;
00906 if (mask & kInvalid ) newm |= FE_ENABLE_INVALID;
00907 if (mask & kDivByZero) newm |= FE_ENABLE_DIVBYZERO;
00908 if (mask & kOverflow ) newm |= FE_ENABLE_OVERFLOW;
00909 if (mask & kUnderflow) newm |= FE_ENABLE_UNDERFLOW;
00910 if (mask & kInexact ) newm |= FE_ENABLE_INEXACT;
00911
00912 Long64_t curmask;
00913 fegetenvd(curmask);
00914 curmask = (curmask & ~FE_ENABLE_ALL_EXCEPT) | newm;
00915 fesetenvd(curmask);
00916 #endif
00917
00918 return old;
00919 }
00920
00921
00922 void TUnixSystem::DispatchOneEvent(Bool_t pendingOnly)
00923 {
00924
00925
00926 Bool_t pollOnce = pendingOnly;
00927
00928 while (1) {
00929
00930 if (gXDisplay && gXDisplay->Notify()) {
00931 if (fReadready->IsSet(gXDisplay->GetFd())) {
00932 fReadready->Clr(gXDisplay->GetFd());
00933 fNfd--;
00934 }
00935 if (!pendingOnly) return;
00936 }
00937
00938
00939 if (fNfd > 0 && fFileHandler && fFileHandler->GetSize() > 0)
00940 if (CheckDescriptors())
00941 if (!pendingOnly) return;
00942 fNfd = 0;
00943 fReadready->Zero();
00944 fWriteready->Zero();
00945
00946 if (pendingOnly && !pollOnce)
00947 return;
00948
00949
00950 if (fSigcnt > 0 && fSignalHandler->GetSize() > 0)
00951 if (CheckSignals(kTRUE))
00952 if (!pendingOnly) return;
00953 fSigcnt = 0;
00954 fSignals->Zero();
00955
00956
00957 Long_t nextto;
00958 if (fTimers && fTimers->GetSize() > 0)
00959 if (DispatchTimers(kTRUE)) {
00960
00961 nextto = NextTimeOut(kTRUE);
00962 if (nextto > kItimerResolution || nextto == -1)
00963 return;
00964 }
00965
00966
00967 nextto = NextTimeOut(kTRUE);
00968 if (pendingOnly) {
00969 if (fFileHandler && fFileHandler->GetSize() == 0)
00970 return;
00971 nextto = 0;
00972 pollOnce = kFALSE;
00973 }
00974
00975
00976 *fReadready = *fReadmask;
00977 *fWriteready = *fWritemask;
00978
00979 int mxfd = TMath::Max(fMaxrfd, fMaxwfd);
00980 mxfd++;
00981
00982
00983 if (mxfd == 0 && nextto == -1)
00984 return;
00985
00986 fNfd = UnixSelect(mxfd, fReadready, fWriteready, nextto);
00987 if (fNfd < 0 && fNfd != -2) {
00988 int fd, rc;
00989 TFdSet t;
00990 for (fd = 0; fd < mxfd; fd++) {
00991 t.Set(fd);
00992 if (fReadmask->IsSet(fd)) {
00993 rc = UnixSelect(fd+1, &t, 0, 0);
00994 if (rc < 0 && rc != -2) {
00995 SysError("DispatchOneEvent", "select: read error on %d\n", fd);
00996 fReadmask->Clr(fd);
00997 }
00998 }
00999 if (fWritemask->IsSet(fd)) {
01000 rc = UnixSelect(fd+1, 0, &t, 0);
01001 if (rc < 0 && rc != -2) {
01002 SysError("DispatchOneEvent", "select: write error on %d\n", fd);
01003 fWritemask->Clr(fd);
01004 }
01005 }
01006 t.Clr(fd);
01007 }
01008 }
01009 }
01010 }
01011
01012
01013 void TUnixSystem::Sleep(UInt_t milliSec)
01014 {
01015
01016
01017 struct timeval tv;
01018
01019 tv.tv_sec = milliSec / 1000;
01020 tv.tv_usec = (milliSec % 1000) * 1000;
01021
01022 select(0, 0, 0, 0, &tv);
01023 }
01024
01025
01026 Int_t TUnixSystem::Select(TList *act, Long_t to)
01027 {
01028
01029
01030
01031
01032
01033
01034
01035 Int_t rc = -4;
01036
01037 TFdSet rd, wr;
01038 Int_t mxfd = -1;
01039 TIter next(act);
01040 TFileHandler *h = 0;
01041 while ((h = (TFileHandler *) next())) {
01042 Int_t fd = h->GetFd();
01043 if (fd > -1) {
01044 if (h->HasReadInterest()) {
01045 rd.Set(fd);
01046 mxfd = TMath::Max(mxfd, fd);
01047 }
01048 if (h->HasWriteInterest()) {
01049 wr.Set(fd);
01050 mxfd = TMath::Max(mxfd, fd);
01051 }
01052 h->ResetReadyMask();
01053 }
01054 }
01055 if (mxfd > -1)
01056 rc = UnixSelect(mxfd+1, &rd, &wr, to);
01057
01058
01059 if (rc > 0) {
01060 next.Reset();
01061 while ((h = (TFileHandler *) next())) {
01062 Int_t fd = h->GetFd();
01063 if (rd.IsSet(fd))
01064 h->SetReadReady();
01065 if (wr.IsSet(fd))
01066 h->SetWriteReady();
01067 }
01068 }
01069
01070 return rc;
01071 }
01072
01073
01074 Int_t TUnixSystem::Select(TFileHandler *h, Long_t to)
01075 {
01076
01077
01078
01079
01080
01081
01082
01083 Int_t rc = -4;
01084
01085 TFdSet rd, wr;
01086 Int_t mxfd = -1;
01087 Int_t fd = -1;
01088 if (h) {
01089 fd = h->GetFd();
01090 if (fd > -1) {
01091 if (h->HasReadInterest())
01092 rd.Set(fd);
01093 if (h->HasWriteInterest())
01094 wr.Set(fd);
01095 h->ResetReadyMask();
01096 mxfd = fd;
01097 rc = UnixSelect(mxfd+1, &rd, &wr, to);
01098 }
01099 }
01100
01101
01102 if (rc > 0) {
01103 if (rd.IsSet(fd))
01104 h->SetReadReady();
01105 if (wr.IsSet(fd))
01106 h->SetWriteReady();
01107 }
01108
01109 return rc;
01110 }
01111
01112
01113
01114
01115 void TUnixSystem::DispatchSignals(ESignals sig)
01116 {
01117
01118
01119 switch (sig) {
01120 case kSigAlarm:
01121 DispatchTimers(kFALSE);
01122 break;
01123 case kSigChild:
01124 CheckChilds();
01125 break;
01126 case kSigBus:
01127 case kSigSegmentationViolation:
01128 case kSigIllegalInstruction:
01129 case kSigFloatingException:
01130 Break("TUnixSystem::DispatchSignals", "%s", UnixSigname(sig));
01131 StackTrace();
01132 if (gApplication)
01133 gApplication->HandleException(sig);
01134 else
01135 Exit(sig);
01136 break;
01137 case kSigSystem:
01138 case kSigPipe:
01139 Break("TUnixSystem::DispatchSignals", "%s", UnixSigname(sig));
01140 break;
01141 case kSigWindowChanged:
01142 Gl_windowchanged();
01143 break;
01144 default:
01145 fSignals->Set(sig);
01146 fSigcnt++;
01147 break;
01148 }
01149
01150
01151 if (fSigcnt > 0 && fSignalHandler->GetSize() > 0)
01152 CheckSignals(kFALSE);
01153 }
01154
01155
01156 Bool_t TUnixSystem::CheckSignals(Bool_t sync)
01157 {
01158
01159
01160 TSignalHandler *sh;
01161 Int_t sigdone = -1;
01162 {
01163 TOrdCollectionIter it((TOrdCollection*)fSignalHandler);
01164
01165 while ((sh = (TSignalHandler*)it.Next())) {
01166 if (sync == sh->IsSync()) {
01167 ESignals sig = sh->GetSignal();
01168 if ((fSignals->IsSet(sig) && sigdone == -1) || sigdone == sig) {
01169 if (sigdone == -1) {
01170 fSignals->Clr(sig);
01171 sigdone = sig;
01172 fSigcnt--;
01173 }
01174 if (sh->IsActive())
01175 sh->Notify();
01176 }
01177 }
01178 }
01179 }
01180 if (sigdone != -1)
01181 return kTRUE;
01182
01183 return kFALSE;
01184 }
01185
01186
01187 void TUnixSystem::CheckChilds()
01188 {
01189
01190
01191 #if 0 //rdm
01192 int pid;
01193 while ((pid = UnixWaitchild()) > 0) {
01194 TIter next(zombieHandler);
01195 register UnixPtty *pty;
01196 while ((pty = (UnixPtty*) next()))
01197 if (pty->GetPid() == pid) {
01198 zombieHandler->RemovePtr(pty);
01199 pty->DiedNotify();
01200 }
01201 }
01202 #endif
01203 }
01204
01205
01206 Bool_t TUnixSystem::CheckDescriptors()
01207 {
01208
01209
01210
01211 TFileHandler *fh;
01212 Int_t fddone = -1;
01213 Bool_t read = kFALSE;
01214 #if defined(R__LINUX) && defined(__alpha__)
01215
01216 Int_t cursor = 0;
01217 while (cursor < fFileHandler->GetSize()) {
01218 fh = (TFileHandler*) fFileHandler->At(cursor++);
01219 #else
01220 TOrdCollectionIter it((TOrdCollection*)fFileHandler);
01221 while ((fh = (TFileHandler*) it.Next())) {
01222 #endif
01223 Int_t fd = fh->GetFd();
01224 if ((fd <= fMaxrfd && fReadready->IsSet(fd) && fddone == -1) ||
01225 (fddone == fd && read)) {
01226 if (fddone == -1) {
01227 fReadready->Clr(fd);
01228 fddone = fd;
01229 read = kTRUE;
01230 fNfd--;
01231 }
01232 if (fh->IsActive())
01233 fh->ReadNotify();
01234 }
01235 if ((fd <= fMaxwfd && fWriteready->IsSet(fd) && fddone == -1) ||
01236 (fddone == fd && !read)) {
01237 if (fddone == -1) {
01238 fWriteready->Clr(fd);
01239 fddone = fd;
01240 read = kFALSE;
01241 fNfd--;
01242 }
01243 if (fh->IsActive())
01244 fh->WriteNotify();
01245 }
01246 }
01247 if (fddone != -1)
01248 return kTRUE;
01249
01250 return kFALSE;
01251 }
01252
01253
01254
01255
01256 int TUnixSystem::MakeDirectory(const char *name)
01257 {
01258
01259
01260
01261 TSystem *helper = FindHelper(name);
01262 if (helper)
01263 return helper->MakeDirectory(name);
01264
01265 return UnixMakedir(name);
01266 }
01267
01268
01269 void *TUnixSystem::OpenDirectory(const char *name)
01270 {
01271
01272
01273 TSystem *helper = FindHelper(name);
01274 if (helper)
01275 return helper->OpenDirectory(name);
01276
01277 return UnixOpendir(name);
01278 }
01279
01280
01281 void TUnixSystem::FreeDirectory(void *dirp)
01282 {
01283
01284
01285 TSystem *helper = FindHelper(0, dirp);
01286 if (helper) {
01287 helper->FreeDirectory(dirp);
01288 return;
01289 }
01290
01291 if (dirp)
01292 ::closedir((DIR*)dirp);
01293 }
01294
01295
01296 const char *TUnixSystem::GetDirEntry(void *dirp)
01297 {
01298
01299
01300 TSystem *helper = FindHelper(0, dirp);
01301 if (helper)
01302 return helper->GetDirEntry(dirp);
01303
01304 if (dirp)
01305 return UnixGetdirentry(dirp);
01306
01307 return 0;
01308 }
01309
01310
01311 Bool_t TUnixSystem::ChangeDirectory(const char *path)
01312 {
01313
01314
01315 Bool_t ret = (Bool_t) (::chdir(path) == 0);
01316 if (fWdpath != "")
01317 fWdpath = "";
01318 return ret;
01319 }
01320
01321
01322 const char *TUnixSystem::WorkingDirectory()
01323 {
01324
01325
01326 if (fWdpath != "")
01327 return fWdpath.Data();
01328
01329 R__LOCKGUARD2(gSystemMutex);
01330
01331 static char cwd[kMAXPATHLEN];
01332 if (::getcwd(cwd, kMAXPATHLEN) == 0) {
01333 fWdpath = "/";
01334 Error("WorkingDirectory", "getcwd() failed");
01335 }
01336 fWdpath = cwd;
01337 return fWdpath.Data();
01338 }
01339
01340
01341 const char *TUnixSystem::HomeDirectory(const char *userName)
01342 {
01343
01344
01345 return UnixHomedirectory(userName);
01346 }
01347
01348
01349 const char *TUnixSystem::TempDirectory() const
01350 {
01351
01352
01353
01354 const char *dir = gSystem->Getenv("TMPDIR");
01355 if (!dir || gSystem->AccessPathName(dir, kWritePermission))
01356 dir = "/tmp";
01357
01358 return dir;
01359 }
01360
01361
01362 FILE *TUnixSystem::TempFileName(TString &base, const char *dir)
01363 {
01364
01365
01366
01367
01368
01369
01370
01371
01372 char *b = ConcatFileName(dir ? dir : TempDirectory(), base);
01373 base = b;
01374 base += "XXXXXX";
01375 delete [] b;
01376
01377 char *arg = StrDup(base);
01378 int fd = mkstemp(arg);
01379 base = arg;
01380 delete [] arg;
01381
01382 if (fd == -1) {
01383 SysError("TempFileName", "%s", base.Data());
01384 return 0;
01385 } else {
01386 FILE *fp = fdopen(fd, "w+");
01387 if (fp == 0)
01388 SysError("TempFileName", "converting filedescriptor (%d)", fd);
01389 return fp;
01390 }
01391 }
01392
01393
01394 const char *TUnixSystem::PrependPathName(const char *dir, TString& name)
01395 {
01396
01397
01398 if (name.IsNull() || name == ".") {
01399 if (dir) {
01400 name = dir;
01401 if (dir[strlen(dir) - 1] != '/')
01402 name += '/';
01403 } else name = "";
01404 return name.Data();
01405 }
01406
01407 if (!dir || !dir[0]) dir = "/";
01408 else if (dir[strlen(dir) - 1] != '/')
01409 name.Prepend('/');
01410 name.Prepend(dir);
01411
01412 return name.Data();
01413 }
01414
01415
01416
01417
01418 Bool_t TUnixSystem::AccessPathName(const char *path, EAccessMode mode)
01419 {
01420
01421
01422
01423
01424 TSystem *helper = FindHelper(path);
01425 if (helper)
01426 return helper->AccessPathName(path, mode);
01427
01428 if (::access(StripOffProto(path, "file:"), mode) == 0)
01429 return kFALSE;
01430 fLastErrorString = GetError();
01431 return kTRUE;
01432 }
01433
01434
01435 int TUnixSystem::CopyFile(const char *f, const char *t, Bool_t overwrite)
01436 {
01437
01438
01439
01440
01441
01442 if (!AccessPathName(t) && !overwrite)
01443 return -2;
01444
01445 FILE *from = fopen(f, "r");
01446 if (!from)
01447 return -1;
01448
01449 FILE *to = fopen(t, "w");
01450 if (!to) {
01451 fclose(from);
01452 return -1;
01453 }
01454
01455 const int bufsize = 1024;
01456 char buf[bufsize];
01457 int ret = 0;
01458 while (!ret && !feof(from)) {
01459 size_t numread = fread (buf, sizeof(char), bufsize, from);
01460 size_t numwritten = fwrite(buf, sizeof(char), numread, to);
01461 if (numread != numwritten)
01462 ret = -3;
01463 }
01464
01465 fclose(from);
01466 fclose(to);
01467
01468 return ret;
01469 }
01470
01471
01472 int TUnixSystem::Rename(const char *f, const char *t)
01473 {
01474
01475
01476 int ret = ::rename(f, t);
01477 fLastErrorString = GetError();
01478 return ret;
01479 }
01480
01481
01482 Bool_t TUnixSystem::IsPathLocal(const char *path)
01483 {
01484
01485
01486
01487 TSystem *helper = FindHelper(path);
01488 if (helper)
01489 return helper->IsPathLocal(path);
01490
01491 return TSystem::IsPathLocal(path);
01492 }
01493
01494
01495 int TUnixSystem::GetPathInfo(const char *path, FileStat_t &buf)
01496 {
01497
01498
01499
01500
01501
01502 TSystem *helper = FindHelper(path);
01503 if (helper)
01504 return helper->GetPathInfo(path, buf);
01505
01506 return UnixFilestat(path, buf);
01507 }
01508
01509
01510 int TUnixSystem::GetFsInfo(const char *path, Long_t *id, Long_t *bsize,
01511 Long_t *blocks, Long_t *bfree)
01512 {
01513
01514
01515
01516
01517
01518
01519
01520
01521 return UnixFSstat(path, id, bsize, blocks, bfree);
01522 }
01523
01524
01525 int TUnixSystem::Link(const char *from, const char *to)
01526 {
01527
01528
01529
01530 return ::link(from, to);
01531 }
01532
01533
01534 int TUnixSystem::Symlink(const char *from, const char *to)
01535 {
01536
01537
01538
01539 #if defined(R__AIX)
01540 return ::symlink((char*)from, (char*)to);
01541 #else
01542 return ::symlink(from, to);
01543 #endif
01544 }
01545
01546
01547 int TUnixSystem::Unlink(const char *name)
01548 {
01549
01550
01551
01552 TSystem *helper = FindHelper(name);
01553 if (helper)
01554 return helper->Unlink(name);
01555
01556 #if defined(R__SEEK64)
01557 struct stat64 finfo;
01558 if (lstat64(name, &finfo) < 0)
01559 #else
01560 struct stat finfo;
01561 if (lstat(name, &finfo) < 0)
01562 #endif
01563 return -1;
01564
01565 if (S_ISDIR(finfo.st_mode))
01566 return ::rmdir(name);
01567 else
01568 return ::unlink(name);
01569 }
01570
01571
01572
01573
01574
01575 const char
01576 #ifdef G__OLDEXPAND
01577 kShellEscape = '\\',
01578 *kShellStuff = "(){}<>\"'",
01579 #endif
01580 *kShellMeta = "~*[]{}?$";
01581
01582
01583 #ifndef G__OLDEXPAND
01584
01585 Bool_t TUnixSystem::ExpandPathName(TString &path)
01586 {
01587
01588
01589
01590
01591
01592
01593 const char *p, *patbuf = (const char *)path;
01594
01595
01596 while (*patbuf == ' ')
01597 patbuf++;
01598
01599
01600 for (p = patbuf; *p; p++)
01601 if (strchr(kShellMeta, *p))
01602 goto expand;
01603
01604 return kFALSE;
01605
01606 expand:
01607
01608 path.ReplaceAll("$(","$");
01609 path.ReplaceAll(")","");
01610
01611 if ((p = ExpandFileName(path))) {
01612 path = p;
01613 return kFALSE;
01614 }
01615 return kTRUE;
01616 }
01617 #endif
01618
01619 #ifdef G__OLDEXPAND
01620
01621 Bool_t TUnixSystem::ExpandPathName(TString &patbuf0)
01622 {
01623
01624
01625
01626
01627
01628
01629 const char *patbuf = (const char *)patbuf0;
01630 const char *hd, *p;
01631
01632 char stuffedPat[kMAXPATHLEN], name[70];
01633 char *q;
01634 FILE *pf;
01635 int ch;
01636
01637
01638 while (*patbuf == ' ')
01639 patbuf++;
01640
01641
01642 for (p = patbuf; *p; p++)
01643 if (strchr(kShellMeta, *p))
01644 goto needshell;
01645
01646 return kFALSE;
01647
01648 needshell:
01649
01650 patbuf0.ReplaceAll("$(","$");
01651 patbuf0.ReplaceAll(")","");
01652
01653
01654 EscChar(patbuf, stuffedPat, sizeof(stuffedPat), (char*)kShellStuff, kShellEscape);
01655
01656 #ifdef R__HPUX
01657 TString cmd("/bin/echo ");
01658 #else
01659 TString cmd("echo ");
01660 #endif
01661
01662
01663 if (stuffedPat[0] == '~') {
01664 if (stuffedPat[1] != '\0' && stuffedPat[1] != '/') {
01665
01666 for (p = &stuffedPat[1], q = name; *p && *p !='/';)
01667 *q++ = *p++;
01668 *q = '\0';
01669 hd = UnixHomedirectory(name);
01670 if (hd == 0)
01671 cmd += stuffedPat;
01672 else {
01673 cmd += hd;
01674 cmd += p;
01675 }
01676 } else {
01677 hd = UnixHomedirectory(0);
01678 if (hd == 0) {
01679 fLastErrorString = GetError();
01680 return kTRUE;
01681 }
01682 cmd += hd;
01683 cmd += &stuffedPat[1];
01684 }
01685 } else
01686 cmd += stuffedPat;
01687
01688 if ((pf = ::popen(cmd.Data(), "r")) == 0) {
01689 fLastErrorString = GetError();
01690 return kTRUE;
01691 }
01692
01693
01694 patbuf0 = "";
01695 int cnt = 0;
01696 #if defined(R__ALPHA) || defined(R__AIX)
01697 again:
01698 #endif
01699 for (ch = fgetc(pf); ch != EOF && ch != ' ' && ch != '\n'; ch = fgetc(pf)) {
01700 patbuf0.Append(ch);
01701 cnt++;
01702 }
01703 #if defined(R__ALPHA) || defined(R__AIX)
01704
01705 if (cnt == 0 && ch == EOF) goto again;
01706 #endif
01707
01708
01709 while (ch != EOF) {
01710 ch = fgetc(pf);
01711 if (ch == ' ' || ch == '\t') {
01712 fLastErrorString = "expression ambigous";
01713 ::pclose(pf);
01714 return kTRUE;
01715 }
01716 }
01717
01718 ::pclose(pf);
01719
01720 return kFALSE;
01721 }
01722 #endif
01723
01724
01725 char *TUnixSystem::ExpandPathName(const char *path)
01726 {
01727
01728
01729
01730
01731
01732
01733 TString patbuf = path;
01734 if (ExpandPathName(patbuf))
01735 return 0;
01736 return StrDup(patbuf.Data());
01737 }
01738
01739
01740 int TUnixSystem::Chmod(const char *file, UInt_t mode)
01741 {
01742
01743
01744 return ::chmod(file, mode);
01745 }
01746
01747
01748 int TUnixSystem::Umask(Int_t mask)
01749 {
01750
01751
01752 return ::umask(mask);
01753 }
01754
01755
01756 int TUnixSystem::Utime(const char *file, Long_t modtime, Long_t actime)
01757 {
01758
01759
01760
01761 if (!actime)
01762 actime = modtime;
01763
01764 struct utimbuf t;
01765 t.actime = (time_t)actime;
01766 t.modtime = (time_t)modtime;
01767 return ::utime(file, &t);
01768 }
01769
01770
01771 const char *TUnixSystem::FindFile(const char *search, TString& wfil, EAccessMode mode)
01772 {
01773
01774
01775
01776
01777
01778 TString show;
01779 if (gEnv->GetValue("Root.ShowPath", 0))
01780 show.Form("Which: %s =", wfil.Data());
01781
01782 gSystem->ExpandPathName(wfil);
01783
01784 if (wfil[0] == '/') {
01785 #if defined(R__SEEK64)
01786 struct stat64 finfo;
01787 if (access(wfil.Data(), mode) == 0 &&
01788 stat64(wfil.Data(), &finfo) == 0 && S_ISREG(finfo.st_mode)) {
01789 #else
01790 struct stat finfo;
01791 if (access(wfil.Data(), mode) == 0 &&
01792 stat(wfil.Data(), &finfo) == 0 && S_ISREG(finfo.st_mode)) {
01793 #endif
01794 if (show != "")
01795 Printf("%s %s", show.Data(), wfil.Data());
01796 return wfil.Data();
01797 }
01798 if (show != "")
01799 Printf("%s <not found>", show.Data());
01800 wfil = "";
01801 return 0;
01802 }
01803
01804 if (search == 0)
01805 search = ".";
01806
01807 TString apwd(gSystem->WorkingDirectory());
01808 apwd += "/";
01809 for (const char* ptr = search; *ptr;) {
01810 TString name;
01811 if (*ptr != '/' && *ptr !='$' && *ptr != '~')
01812 name = apwd;
01813 const char* posEndOfPart = strchr(ptr, ':');
01814 if (posEndOfPart) {
01815 name.Append(ptr, posEndOfPart - ptr);
01816 ptr = posEndOfPart + 1;
01817 } else {
01818 name.Append(ptr);
01819 ptr += strlen(ptr);
01820 }
01821
01822 if (!name.EndsWith("/"))
01823 name += '/';
01824 name += wfil;
01825
01826 gSystem->ExpandPathName(name);
01827 #if defined(R__SEEK64)
01828 struct stat64 finfo;
01829 if (access(name.Data(), mode) == 0 &&
01830 stat64(name.Data(), &finfo) == 0 && S_ISREG(finfo.st_mode)) {
01831 #else
01832 struct stat finfo;
01833 if (access(name.Data(), mode) == 0 &&
01834 stat(name.Data(), &finfo) == 0 && S_ISREG(finfo.st_mode)) {
01835 #endif
01836 if (show != "")
01837 Printf("%s %s", show.Data(), name.Data());
01838 wfil = name;
01839 return wfil.Data();
01840 }
01841 }
01842
01843 if (show != "")
01844 Printf("%s <not found>", show.Data());
01845 wfil = "";
01846 return 0;
01847 }
01848
01849
01850
01851
01852 Int_t TUnixSystem::GetUid(const char *user)
01853 {
01854
01855
01856 if (!user || !user[0])
01857 return getuid();
01858 else {
01859 struct passwd *apwd = getpwnam(user);
01860 if (apwd)
01861 return apwd->pw_uid;
01862 }
01863 return 0;
01864 }
01865
01866
01867 Int_t TUnixSystem::GetEffectiveUid()
01868 {
01869
01870
01871
01872 return geteuid();
01873 }
01874
01875
01876 Int_t TUnixSystem::GetGid(const char *group)
01877 {
01878
01879
01880 if (!group || !group[0])
01881 return getgid();
01882 else {
01883 struct group *grp = getgrnam(group);
01884 if (grp)
01885 return grp->gr_gid;
01886 }
01887 return 0;
01888 }
01889
01890
01891 Int_t TUnixSystem::GetEffectiveGid()
01892 {
01893
01894
01895
01896 return getegid();
01897 }
01898
01899
01900 UserGroup_t *TUnixSystem::GetUserInfo(Int_t uid)
01901 {
01902
01903
01904
01905 typedef std::map<Int_t , UserGroup_t> UserInfoCache_t;
01906 static UserInfoCache_t gUserInfo;
01907
01908 UserInfoCache_t::const_iterator iUserInfo = gUserInfo.find(uid);
01909 if (iUserInfo != gUserInfo.end())
01910 return new UserGroup_t(iUserInfo->second);
01911
01912 struct passwd *apwd = getpwuid(uid);
01913 if (apwd) {
01914 UserGroup_t *ug = new UserGroup_t;
01915 ug->fUid = apwd->pw_uid;
01916 ug->fGid = apwd->pw_gid;
01917 ug->fUser = apwd->pw_name;
01918 ug->fPasswd = apwd->pw_passwd;
01919 ug->fRealName = apwd->pw_gecos;
01920 ug->fShell = apwd->pw_shell;
01921 UserGroup_t *gr = GetGroupInfo(apwd->pw_gid);
01922 if (gr) ug->fGroup = gr->fGroup;
01923 delete gr;
01924
01925 gUserInfo[uid] = *ug;
01926 return ug;
01927 }
01928 return 0;
01929 }
01930
01931
01932 UserGroup_t *TUnixSystem::GetUserInfo(const char *user)
01933 {
01934
01935
01936
01937
01938 return GetUserInfo(GetUid(user));
01939 }
01940
01941
01942 UserGroup_t *TUnixSystem::GetGroupInfo(Int_t gid)
01943 {
01944
01945
01946
01947
01948
01949
01950 struct group *grp = getgrgid(gid);
01951 if (grp) {
01952 UserGroup_t *gr = new UserGroup_t;
01953 gr->fUid = 0;
01954 gr->fGid = grp->gr_gid;
01955 gr->fGroup = grp->gr_name;
01956 return gr;
01957 }
01958 return 0;
01959 }
01960
01961
01962 UserGroup_t *TUnixSystem::GetGroupInfo(const char *group)
01963 {
01964
01965
01966
01967
01968
01969
01970 return GetGroupInfo(GetGid(group));
01971 }
01972
01973
01974
01975
01976 void TUnixSystem::Setenv(const char *name, const char *value)
01977 {
01978
01979
01980
01981
01982
01983
01984 char *s = new char [strlen(name)+strlen(value) + 2];
01985 sprintf(s, "%s=%s", name, value);
01986
01987 ::putenv(s);
01988 }
01989
01990
01991 const char *TUnixSystem::Getenv(const char *name)
01992 {
01993
01994
01995 return ::getenv(name);
01996 }
01997
01998
01999
02000
02001 int TUnixSystem::Exec(const char *shellcmd)
02002 {
02003
02004
02005 return ::system(shellcmd);
02006 }
02007
02008
02009 FILE *TUnixSystem::OpenPipe(const char *command, const char *mode)
02010 {
02011
02012
02013 return ::popen(command, mode);
02014 }
02015
02016
02017 int TUnixSystem::ClosePipe(FILE *pipe)
02018 {
02019
02020
02021 return ::pclose(pipe);
02022 }
02023
02024
02025 int TUnixSystem::GetPid()
02026 {
02027
02028
02029 return ::getpid();
02030 }
02031
02032
02033 void TUnixSystem::Exit(int code, Bool_t mode)
02034 {
02035
02036
02037
02038 if (gROOT) {
02039 if (gROOT->GetListOfFiles()) gROOT->GetListOfFiles()->Delete("slow");
02040 if (gROOT->GetListOfSockets()) gROOT->GetListOfSockets()->Delete();
02041 if (gROOT->GetListOfMappedFiles()) gROOT->GetListOfMappedFiles()->Delete("slow");
02042 }
02043
02044 if (mode)
02045 ::exit(code);
02046 else
02047 ::_exit(code);
02048 }
02049
02050
02051 void TUnixSystem::Abort(int)
02052 {
02053
02054
02055 ::abort();
02056 }
02057
02058
02059 void TUnixSystem::StackTrace()
02060 {
02061
02062
02063 if (!gEnv->GetValue("Root.Stacktrace", 1))
02064 return;
02065
02066 #if defined(R__MACOSX) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
02067 if (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) {
02068 fprintf(stderr, "Info in <TUnixSystem::StackTrace> function not supported on iOS\n");
02069 return;
02070 }
02071 #endif
02072
02073 TString gdbscript = gEnv->GetValue("Root.StacktraceScript", "");
02074 gdbscript = gdbscript.Strip();
02075 if (gdbscript != "") {
02076 if (AccessPathName(gdbscript, kReadPermission)) {
02077 fprintf(stderr, "Root.StacktraceScript %s does not exist\n", gdbscript.Data());
02078 gdbscript = "";
02079 } else {
02080 gdbscript += " ";
02081 }
02082 }
02083 if (gdbscript == "") {
02084 #ifdef ROOTETCDIR
02085 gdbscript.Form("%s/gdb-backtrace.sh", ROOTETCDIR);
02086 #else
02087 gdbscript.Form("%s/etc/gdb-backtrace.sh", gSystem->Getenv("ROOTSYS"));
02088 #endif
02089 if (AccessPathName(gdbscript, kReadPermission)) {
02090 fprintf(stderr, "Error in <TUnixSystem::StackTrace> script %s is missing\n", gdbscript.Data());
02091 return;
02092 }
02093 gdbscript += " ";
02094 }
02095
02096 TString gdbmess = gEnv->GetValue("Root.StacktraceMessage", "");
02097 gdbmess = gdbmess.Strip();
02098
02099 cout.flush();
02100 fflush(stdout);
02101
02102 cerr.flush();
02103 fflush(stderr);
02104
02105 int fd = STDERR_FILENO;
02106
02107 const char *message = " Generating stack trace...\n";
02108
02109 if (fd && message) { }
02110
02111 if (gApplication && !strcmp(gApplication->GetName(), "TRint"))
02112 Getlinem(kCleanUp, 0);
02113
02114 #if defined(USE_GDB_STACK_TRACE)
02115 char *gdb = Which(Getenv("PATH"), "gdb", kExecutePermission);
02116 if (!gdb) {
02117 fprintf(stderr, "gdb not found, need it for stack trace\n");
02118 return;
02119 }
02120
02121
02122 TString gdbmessf = "gdb-message";
02123 if (gdbmess != "") {
02124 FILE *f = TempFileName(gdbmessf);
02125 fprintf(f, "%s\n", gdbmess.Data());
02126 fclose(f);
02127 }
02128
02129
02130 gdbscript += GetExePath();
02131 gdbscript += " ";
02132 gdbscript += GetPid();
02133 if (gdbmess != "") {
02134 gdbscript += " ";
02135 gdbscript += gdbmessf;
02136 }
02137 gdbscript += " 1>&2";
02138 Exec(gdbscript);
02139 delete [] gdb;
02140 return;
02141
02142 #elif defined(HAVE_U_STACK_TRACE) || defined(HAVE_XL_TRBK) // hp-ux, aix
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155 # if defined(HAVE_U_STACK_TRACE) // hp-ux
02156 U_STACK_TRACE();
02157 # elif defined(HAVE_XL_TRBK) // aix
02158 xl__trbk();
02159 # endif
02160
02161
02162
02163
02164
02165 #elif defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_DLADDR) // linux
02166
02167
02168
02169
02170 Bool_t demangle = kTRUE;
02171
02172
02173 const char *cppfilt = "c++filt";
02174 const char *cppfiltarg = "";
02175 #ifdef R__B64
02176 const char *format1 = " 0x%016lx in %.200s %s 0x%lx from %.200s\n";
02177 const char *format2 = " 0x%016lx in %.200s at %.200s from %.200s\n";
02178 const char *format3 = " 0x%016lx in %.200s from %.200s\n";
02179 const char *format4 = " 0x%016lx in <unknown function>\n";
02180 #else
02181 const char *format1 = " 0x%08lx in %.200s %s 0x%lx from %.200s\n";
02182 const char *format2 = " 0x%08lx in %.200s at %.200s from %.200s\n";
02183 const char *format3 = " 0x%08lx in %.200s from %.200s\n";
02184 const char *format4 = " 0x%08lx in <unknown function>\n";
02185 #endif
02186
02187 char *filter = Which(Getenv("PATH"), cppfilt, kExecutePermission);
02188 if (!filter)
02189 demangle = kFALSE;
02190
02191 #if (__GNUC__ >= 3)
02192
02193 if (filter) {
02194 FILE *p = OpenPipe(TString::Format("%s --help 2>&1", filter), "r");
02195 TString help;
02196 while (help.Gets(p)) {
02197 if (help.Index("gnu-v3") != kNPOS) {
02198 cppfiltarg = "--format=gnu-v3";
02199 break;
02200 } else if (help.Index("gnu-new-abi") != kNPOS) {
02201 cppfiltarg = "--format=gnu-new-abi";
02202 break;
02203 }
02204 }
02205 ClosePipe(p);
02206 }
02207 #endif
02208
02209
02210 char *gdb = Which(Getenv("PATH"), "gdb", kExecutePermission);
02211 if (gdb) {
02212
02213 TString gdbmessf = "gdb-message";
02214 if (gdbmess != "") {
02215 FILE *f = TempFileName(gdbmessf);
02216 fprintf(f, "%s\n", gdbmess.Data());
02217 fclose(f);
02218 }
02219
02220
02221 gdbscript += GetPid();
02222 if (gdbmess != "") {
02223 gdbscript += " ";
02224 gdbscript += gdbmessf;
02225 }
02226 gdbscript += " 1>&2";
02227 Exec(gdbscript);
02228 delete [] gdb;
02229 } else {
02230
02231
02232 char *addr2line = Which(Getenv("PATH"), "addr2line", kExecutePermission);
02233 if (addr2line) {
02234
02235 if (write(fd, message, strlen(message)) < 0)
02236 Warning("StackTrace", "problems writing line numbers (errno: %d)", TSystem::GetErrno());
02237 }
02238
02239
02240 TString tmpf1 = "gdb-backtrace";
02241 ofstream file1;
02242 if (demangle) {
02243 FILE *f = TempFileName(tmpf1);
02244 if (f) fclose(f);
02245 file1.open(tmpf1);
02246 if (!file1) {
02247 Error("StackTrace", "could not open file %s", tmpf1.Data());
02248 Unlink(tmpf1);
02249 demangle = kFALSE;
02250 }
02251 }
02252
02253 char buffer[4096];
02254 void *trace[kMAX_BACKTRACE_DEPTH];
02255 int depth = backtrace(trace, kMAX_BACKTRACE_DEPTH);
02256 for (int n = 5; n < depth; n++) {
02257 ULong_t addr = (ULong_t) trace[n];
02258 Dl_info info;
02259
02260 if (dladdr(trace[n], &info) && info.dli_fname && info.dli_fname[0]) {
02261 const char *libname = info.dli_fname;
02262 const char *symname = (info.dli_sname && info.dli_sname[0]) ?
02263 info.dli_sname : "<unknown>";
02264 ULong_t libaddr = (ULong_t) info.dli_fbase;
02265 ULong_t symaddr = (ULong_t) info.dli_saddr;
02266 Bool_t gte = (addr >= symaddr);
02267 ULong_t diff = (gte) ? addr - symaddr : symaddr - addr;
02268 if (addr2line && symaddr) {
02269 ULong_t offset = (addr >= libaddr) ? addr - libaddr :
02270 libaddr - addr;
02271 TString name = TString(libname);
02272 Bool_t noPath = kFALSE;
02273 Bool_t noShare = kTRUE;
02274 if (name[0] != '/') noPath = kTRUE;
02275 if (name.Contains(".so") || name.Contains(".sl")) noShare = kFALSE;
02276 if (noShare) offset = addr;
02277 if (noPath) name = "`which " + name + "`";
02278 snprintf(buffer, sizeof(buffer), "%s -e %s 0x%016lx", addr2line, name.Data(), offset);
02279 Bool_t nodebug = kTRUE;
02280 if (FILE *pf = ::popen(buffer, "r")) {
02281 char buf[2048];
02282 if (fgets(buf, 2048, pf)) {
02283 buf[strlen(buf)-1] = 0;
02284 if (strncmp(buf, "??", 2)) {
02285 snprintf(buffer, sizeof(buffer), format2, addr, symname, buf, libname);
02286 nodebug = kFALSE;
02287 }
02288 }
02289 ::pclose(pf);
02290 }
02291 if (nodebug)
02292 snprintf(buffer, sizeof(buffer), format1, addr, symname,
02293 gte ? "+" : "-", diff, libname);
02294 } else {
02295 if (symaddr)
02296 snprintf(buffer, sizeof(buffer), format1, addr, symname,
02297 gte ? "+" : "-", diff, libname);
02298 else
02299 snprintf(buffer, sizeof(buffer), format3, addr, symname, libname);
02300 }
02301 } else {
02302 snprintf(buffer, sizeof(buffer), format4, addr);
02303 }
02304
02305 if (demangle)
02306 file1 << buffer;
02307 else
02308 if (write(fd, buffer, ::strlen(buffer)) < 0)
02309 Warning("StackTrace", "problems writing buffer (errno: %d)", TSystem::GetErrno());
02310 }
02311
02312 if (demangle) {
02313 TString tmpf2 = "gdb-backtrace";
02314 FILE *f = TempFileName(tmpf2);
02315 if (f) fclose(f);
02316 file1.close();
02317 snprintf(buffer, sizeof(buffer), "%s %s < %s > %s", filter, cppfiltarg, tmpf1.Data(), tmpf2.Data());
02318 Exec(buffer);
02319 ifstream file2(tmpf2);
02320 TString line;
02321 while (file2) {
02322 line = "";
02323 line.ReadString(file2);
02324 if (write(fd, line.Data(), line.Length()) < 0)
02325 Warning("StackTrace", "problems writing line (errno: %d)", TSystem::GetErrno());
02326 }
02327 file2.close();
02328 Unlink(tmpf1);
02329 Unlink(tmpf2);
02330 }
02331
02332 delete [] addr2line;
02333 delete [] filter;
02334 }
02335 #elif defined(PROG_PSTACK) // solaris
02336 # ifdef PROG_CXXFILT
02337 # define CXXFILTER " | " PROG_CXXFILT
02338 # else
02339 # define CXXFILTER
02340 # endif
02341
02342 char buffer[sizeof(PROG_PSTACK) + 64 + 3 + sizeof(PROG_CXXFILT) + 64];
02343 sprintf(buffer, "%s %lu%s 1>&%d", PROG_PSTACK, (ULong_t) getpid(),
02344 "" CXXFILTER, fd);
02345 buffer[sizeof (buffer)-1] = 0;
02346 Exec(buffer);
02347 # undef CXXFILTER
02348
02349 #elif defined(HAVE_EXCPT_H) && defined(HAVE_PDSC_H) && \
02350 defined(HAVE_RLD_INTERFACE_H) // tru64
02351
02352
02353
02354
02355 char buffer [128];
02356 sigcontext context;
02357 int rc = 0;
02358
02359 exc_capture_context (&context);
02360 while (!rc && context.sc_pc) {
02361
02362 pdsc_crd *func, *base, *crd
02363 = exc_remote_lookup_function_entry(0, 0, context.sc_pc, 0, &func, &base);
02364 Elf32_Addr addr = PDSC_CRD_BEGIN_ADDRESS(base, func);
02365
02366 const char *name = "<unknown function>";
02367 sprintf(buffer, " 0x%012lx %.200s + 0x%lx\n",
02368 context.sc_pc, name, context.sc_pc - addr);
02369 write(fd, buffer, ::strlen(buffer));
02370 rc = exc_virtual_unwind(0, &context);
02371 }
02372
02373 #elif defined(HAVE_EXCEPTION_H) && defined(__sgi) // irix
02374
02375
02376
02377
02378
02379 char buffer [340];
02380 sigcontext context;
02381
02382 exc_setjmp(&context);
02383 while (context.sc_pc >= 4) {
02384
02385
02386
02387
02388
02389
02390 char *name = 0;
02391 const char *libname = 0;
02392 const char *symname = 0;
02393 Elf32_Addr offset = ~0L;
02394
02395
02396 Elf32_Addr pc = context.sc_pc;
02397 Dwarf_Fde fde = find_fde_name(&pc, &name);
02398 Dwarf_Addr low_pc = context.sc_pc;
02399 Dwarf_Unsigned udummy;
02400 Dwarf_Signed sdummy;
02401 Dwarf_Ptr pdummy;
02402 Dwarf_Off odummy;
02403 Dwarf_Error err;
02404
02405 symname = name;
02406
02407
02408 if (dwarf_get_fde_range(fde, &low_pc, &udummy, &pdummy, &udummy,
02409 &odummy, &sdummy, &odummy, &err) == DW_DLV_OK)
02410 offset = context.sc_pc - low_pc;
02411
02412
02413
02414
02415
02416
02417
02418
02419 Elf32_Addr addr = context.sc_pc;
02420 Dl_info info;
02421
02422 if (_rld_new_interface (_RLD_DLADDR, addr, &info)) {
02423 if (info.dli_fname && info.dli_fname [0])
02424 libname = info.dli_fname;
02425
02426 Elf32_Addr symaddr = (Elf32_Addr) info.dli_saddr;
02427 if (symaddr == low_pc)
02428 offset = addr - symaddr;
02429 else if (info.dli_sname
02430 && info.dli_sname [0]
02431 && addr - symaddr < offset) {
02432 offset = addr - symaddr;
02433 symname = info.dli_sname;
02434 }
02435 }
02436
02437
02438 if (libname && symname)
02439 write(fd, buffer, sprintf
02440 (buffer, " 0x%012lx %.200s + 0x%lx [%.200s]\n",
02441 addr, symname, offset, libname));
02442 else if (symname)
02443 write(fd, buffer, sprintf
02444 (buffer, " 0x%012lx %.200s + 0x%lx\n",
02445 addr, symname, offset));
02446 else
02447 write(fd, buffer, sprintf
02448 (buffer, " 0x%012lx <unknown function>\n", addr));
02449
02450
02451 free(name);
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462 if (pc != context.sc_pc)
02463 break;
02464
02465 exc_unwind(&context, fde);
02466 }
02467 #endif
02468 }
02469
02470
02471
02472
02473 void TUnixSystem::Openlog(const char *name, Int_t options, ELogFacility facility)
02474 {
02475
02476
02477
02478 int fac = 0;
02479
02480 switch (facility) {
02481 case kLogLocal0:
02482 fac = LOG_LOCAL0;
02483 break;
02484 case kLogLocal1:
02485 fac = LOG_LOCAL1;
02486 break;
02487 case kLogLocal2:
02488 fac = LOG_LOCAL2;
02489 break;
02490 case kLogLocal3:
02491 fac = LOG_LOCAL3;
02492 break;
02493 case kLogLocal4:
02494 fac = LOG_LOCAL4;
02495 break;
02496 case kLogLocal5:
02497 fac = LOG_LOCAL5;
02498 break;
02499 case kLogLocal6:
02500 fac = LOG_LOCAL6;
02501 break;
02502 case kLogLocal7:
02503 fac = LOG_LOCAL7;
02504 break;
02505 }
02506
02507 ::openlog(name, options, fac);
02508 }
02509
02510
02511 void TUnixSystem::Syslog(ELogLevel level, const char *mess)
02512 {
02513
02514
02515
02516
02517 ::syslog(level, "%s", mess);
02518 }
02519
02520
02521 void TUnixSystem::Closelog()
02522 {
02523
02524
02525 ::closelog();
02526 }
02527
02528
02529
02530
02531 Int_t TUnixSystem::RedirectOutput(const char *file, const char *mode,
02532 RedirectHandle_t *h)
02533 {
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546 static RedirectHandle_t loch;
02547
02548 Int_t rc = 0;
02549
02550
02551 RedirectHandle_t *xh = (h) ? h : &loch;
02552
02553 if (file) {
02554
02555 Bool_t outdone = kFALSE;
02556 if (xh->fStdOutTty.IsNull()) {
02557 const char *tty = ttyname(STDOUT_FILENO);
02558 if (tty) {
02559 xh->fStdOutTty = tty;
02560 } else {
02561 if ((xh->fStdOutDup = dup(STDOUT_FILENO)) < 0) {
02562 SysError("RedirectOutput", "could not 'dup' stdout (errno: %d)", TSystem::GetErrno());
02563 return -1;
02564 }
02565 outdone = kTRUE;
02566 }
02567 }
02568 if (xh->fStdErrTty.IsNull()) {
02569 const char *tty = ttyname(STDERR_FILENO);
02570 if (tty) {
02571 xh->fStdErrTty = tty;
02572 } else {
02573 if ((xh->fStdErrDup = dup(STDERR_FILENO)) < 0) {
02574 SysError("RedirectOutput", "could not 'dup' stderr (errno: %d)", TSystem::GetErrno());
02575 if (outdone && dup2(xh->fStdOutDup, STDOUT_FILENO) < 0) {
02576 Warning("RedirectOutput", "could not restore stdout (back to original redirected"
02577 " file) (errno: %d)", TSystem::GetErrno());
02578 }
02579 return -1;
02580 }
02581 }
02582 }
02583
02584
02585 const char *m = (mode[0] == 'a' || mode[0] == 'w') ? mode : "a";
02586
02587
02588 xh->fReadOffSet = 0;
02589 if (m[0] == 'a') {
02590
02591 FileStat_t st;
02592 if (!gSystem->GetPathInfo(file, st))
02593 xh->fReadOffSet = (st.fSize > 0) ? st.fSize : xh->fReadOffSet;
02594 }
02595 xh->fFile = file;
02596
02597
02598 if (freopen(file, m, stdout) == 0) {
02599 SysError("RedirectOutput", "could not freopen stdout (errno: %d)", TSystem::GetErrno());
02600 return -1;
02601 }
02602 if (freopen(file, m, stderr) == 0) {
02603 SysError("RedirectOutput", "could not freopen stderr (errno: %d)", TSystem::GetErrno());
02604 if (freopen(xh->fStdOutTty.Data(), "a", stdout) == 0)
02605 SysError("RedirectOutput", "could not restore stdout (errno: %d)", TSystem::GetErrno());
02606 return -1;
02607 }
02608 } else {
02609
02610 fflush(stdout);
02611 if (!(xh->fStdOutTty.IsNull())) {
02612 if (freopen(xh->fStdOutTty.Data(), "a", stdout) == 0) {
02613 SysError("RedirectOutput", "could not restore stdout (errno: %d)", TSystem::GetErrno());
02614 rc = -1;
02615 }
02616 xh->fStdOutTty = "";
02617 } else {
02618 if (dup2(xh->fStdOutDup, STDOUT_FILENO) < 0) {
02619 SysError("RedirectOutput", "could not restore stdout (back to original redirected"
02620 " file) (errno: %d)", TSystem::GetErrno());
02621 rc = -1;
02622 }
02623 }
02624 fflush(stderr);
02625 if (!(xh->fStdErrTty.IsNull())) {
02626 if (freopen(xh->fStdErrTty.Data(), "a", stderr) == 0) {
02627 SysError("RedirectOutput", "could not restore stderr (errno: %d)", TSystem::GetErrno());
02628 rc = -1;
02629 }
02630 xh->fStdErrTty = "";
02631 } else {
02632 if (dup2(xh->fStdErrDup, STDERR_FILENO) < 0) {
02633 SysError("RedirectOutput", "could not restore stderr (back to original redirected"
02634 " file) (errno: %d)", TSystem::GetErrno());
02635 rc = -1;
02636 }
02637 }
02638
02639 if (xh == &loch)
02640 xh->Reset();
02641 }
02642 return rc;
02643 }
02644
02645
02646
02647
02648 Func_t TUnixSystem::DynFindSymbol(const char *module, const char *entry)
02649 {
02650
02651 #ifdef NOCINT
02652 return UnixDynFindSymbol(module,entry);
02653 #else
02654 if (module) { }
02655 return TSystem::DynFindSymbol("*", entry);
02656 #endif
02657 }
02658
02659
02660 int TUnixSystem::Load(const char *module, const char *entry, Bool_t system)
02661 {
02662
02663
02664
02665
02666 #ifdef NOCINT
02667 int i = UnixDynLoad(module);
02668 if (!entry || !strlen(entry)) return i;
02669
02670 Func_t f = UnixDynFindSymbol(module, entry);
02671 if (f) return 0;
02672 return -1;
02673 #else
02674 return TSystem::Load(module, entry, system);
02675 #endif
02676 }
02677
02678
02679 void TUnixSystem::Unload(const char *module)
02680 {
02681
02682
02683 #ifdef NOCINT
02684 UnixDynUnload(module);
02685 #else
02686 if (module) { TSystem::Unload(module); }
02687 #endif
02688 }
02689
02690
02691 void TUnixSystem::ListSymbols(const char *module, const char *regexp)
02692 {
02693
02694
02695 UnixDynListSymbols(module, regexp);
02696 }
02697
02698
02699 void TUnixSystem::ListLibraries(const char *regexp)
02700 {
02701
02702
02703 #ifdef R__HPUX
02704 UnixDynListLibs(regexp);
02705 #else
02706 TSystem::ListLibraries(regexp);
02707 #endif
02708 }
02709
02710
02711 const char *TUnixSystem::GetLinkedLibraries()
02712 {
02713
02714
02715
02716 #if !defined(R__MACOSX)
02717 if (!gApplication) return 0;
02718 #endif
02719
02720 static Bool_t once = kFALSE;
02721 static TString linkedLibs;
02722
02723 R__LOCKGUARD2(gSystemMutex);
02724
02725 if (!linkedLibs.IsNull())
02726 return linkedLibs;
02727
02728 if (once)
02729 return 0;
02730
02731 #if !defined(R__MACOSX)
02732 char *exe = gSystem->Which(Getenv("PATH"), gApplication->Argv(0),
02733 kExecutePermission);
02734 if (!exe) {
02735 once = kTRUE;
02736 return 0;
02737 }
02738 #endif
02739
02740 #if defined(R__MACOSX)
02741 char *exe = 0;
02742 DylibAdded(0, 0);
02743 linkedLibs = gLinkedDylibs;
02744 #if 0
02745 FILE *p = OpenPipe(TString::Format("otool -L %s", exe), "r");
02746 TString otool;
02747 while (otool.Gets(p)) {
02748 TString delim(" \t");
02749 TObjArray *tok = otool.Tokenize(delim);
02750 TString dylib = ((TObjString*)tok->At(0))->String();
02751 if (dylib.EndsWith(".dylib") && !dylib.Contains("/libSystem.B.dylib")) {
02752 if (!linkedLibs.IsNull())
02753 linkedLibs += " ";
02754 linkedLibs += dylib;
02755 }
02756 delete tok;
02757 }
02758 if (p) {
02759 ClosePipe(p);
02760 }
02761 #endif
02762 #elif defined(R__LINUX) || defined(R__SOLARIS)
02763 #if defined(R__WINGCC )
02764 const char *cLDD="cygcheck";
02765 const char *cSOEXT=".dll";
02766 size_t lenexe = strlen(exe);
02767 if (strcmp(exe + lenexe - 4, ".exe")
02768 && strcmp(exe + lenexe - 4, ".dll")) {
02769
02770
02771 char* longerexe = new char[lenexe + 5];
02772 strlcpy(longerexe, exe,lenexe+5);
02773 strlcat(longerexe, ".exe",lenexe+5);
02774 delete [] exe;
02775 exe = longerexe;
02776 }
02777 #else
02778 const char *cLDD="ldd";
02779 const char *cSOEXT=".so";
02780 #endif
02781 FILE *p = OpenPipe(TString::Format("%s %s", cLDD, exe), "r");
02782 TString ldd;
02783 while (ldd.Gets(p)) {
02784 TString delim(" \t");
02785 TObjArray *tok = ldd.Tokenize(delim);
02786
02787
02788
02789 TObjString *solibName = (TObjString*)tok->At(2);
02790 if (!solibName) {
02791
02792
02793 solibName = (TObjString*)tok->At(0);
02794 }
02795 if (solibName) {
02796 TString solib = solibName->String();
02797 if (solib.EndsWith(cSOEXT)) {
02798 if (!linkedLibs.IsNull())
02799 linkedLibs += " ";
02800 linkedLibs += solib;
02801 }
02802 }
02803 delete tok;
02804 }
02805 ClosePipe(p);
02806 #endif
02807
02808 delete [] exe;
02809
02810 once = kTRUE;
02811
02812 if (linkedLibs.IsNull())
02813 return 0;
02814
02815 return linkedLibs;
02816 }
02817
02818
02819
02820
02821 TTime TUnixSystem::Now()
02822 {
02823
02824
02825 return UnixNow();
02826 }
02827
02828
02829 Bool_t TUnixSystem::DispatchTimers(Bool_t mode)
02830 {
02831
02832
02833
02834 if (!fTimers) return kFALSE;
02835
02836 fInsideNotify = kTRUE;
02837
02838 TOrdCollectionIter it((TOrdCollection*)fTimers);
02839 TTimer *t;
02840 Bool_t timedout = kFALSE;
02841
02842 while ((t = (TTimer *) it.Next())) {
02843
02844 Long64_t now = UnixNow();
02845 if (mode && t->IsSync()) {
02846 if (t->CheckTimer(now))
02847 timedout = kTRUE;
02848 } else if (!mode && t->IsAsync()) {
02849 if (t->CheckTimer(now)) {
02850 UnixSetitimer(NextTimeOut(kFALSE));
02851 timedout = kTRUE;
02852 }
02853 }
02854 }
02855 fInsideNotify = kFALSE;
02856 return timedout;
02857 }
02858
02859
02860 void TUnixSystem::AddTimer(TTimer *ti)
02861 {
02862
02863
02864 TSystem::AddTimer(ti);
02865 ResetTimer(ti);
02866 }
02867
02868
02869 TTimer *TUnixSystem::RemoveTimer(TTimer *ti)
02870 {
02871
02872
02873 if (!ti) return 0;
02874
02875 R__LOCKGUARD2(gSystemMutex);
02876
02877 TTimer *t = TSystem::RemoveTimer(ti);
02878 if (ti->IsAsync())
02879 UnixSetitimer(NextTimeOut(kFALSE));
02880 return t;
02881 }
02882
02883
02884 void TUnixSystem::ResetTimer(TTimer *ti)
02885 {
02886
02887
02888 if (!fInsideNotify && ti && ti->IsAsync())
02889 UnixSetitimer(NextTimeOut(kFALSE));
02890 }
02891
02892
02893
02894
02895 TInetAddress TUnixSystem::GetHostByName(const char *hostname)
02896 {
02897
02898
02899
02900
02901 struct hostent *host_ptr;
02902 const char *host;
02903 int type;
02904 UInt_t addr;
02905
02906 #ifdef HASNOT_INETATON
02907 if ((addr = (UInt_t)inet_addr(hostname)) != INADDR_NONE) {
02908 #else
02909 struct in_addr ad;
02910 if (inet_aton(hostname, &ad)) {
02911 memcpy(&addr, &ad.s_addr, sizeof(ad.s_addr));
02912 #endif
02913 type = AF_INET;
02914 if ((host_ptr = gethostbyaddr((const char *)&addr,
02915 sizeof(addr), AF_INET))) {
02916 host = host_ptr->h_name;
02917 TInetAddress a(host, ntohl(addr), type);
02918 UInt_t addr2;
02919 Int_t i;
02920 for (i = 1; host_ptr->h_addr_list[i]; i++) {
02921 memcpy(&addr2, host_ptr->h_addr_list[i], host_ptr->h_length);
02922 a.AddAddress(ntohl(addr2));
02923 }
02924 for (i = 0; host_ptr->h_aliases[i]; i++)
02925 a.AddAlias(host_ptr->h_aliases[i]);
02926 return a;
02927 } else {
02928 host = "UnNamedHost";
02929 }
02930 } else if ((host_ptr = gethostbyname(hostname))) {
02931
02932 if (host_ptr->h_addrtype != AF_INET) {
02933 Error("GetHostByName", "%s is not an internet host\n", hostname);
02934 return TInetAddress();
02935 }
02936 memcpy(&addr, host_ptr->h_addr, host_ptr->h_length);
02937 host = host_ptr->h_name;
02938 type = host_ptr->h_addrtype;
02939 TInetAddress a(host, ntohl(addr), type);
02940 UInt_t addr2;
02941 Int_t i;
02942 for (i = 1; host_ptr->h_addr_list[i]; i++) {
02943 memcpy(&addr2, host_ptr->h_addr_list[i], host_ptr->h_length);
02944 a.AddAddress(ntohl(addr2));
02945 }
02946 for (i = 0; host_ptr->h_aliases[i]; i++)
02947 a.AddAlias(host_ptr->h_aliases[i]);
02948 return a;
02949 } else {
02950 if (gDebug > 0) Error("GetHostByName", "unknown host %s", hostname);
02951 return TInetAddress(hostname, 0, -1);
02952 }
02953
02954 return TInetAddress(host, ntohl(addr), type);
02955 }
02956
02957
02958 TInetAddress TUnixSystem::GetSockName(int sock)
02959 {
02960
02961
02962 struct sockaddr_in addr;
02963 #if defined(USE_SIZE_T)
02964 size_t len = sizeof(addr);
02965 #elif defined(USE_SOCKLEN_T)
02966 socklen_t len = sizeof(addr);
02967 #else
02968 int len = sizeof(addr);
02969 #endif
02970
02971 if (getsockname(sock, (struct sockaddr *)&addr, &len) == -1) {
02972 SysError("GetSockName", "getsockname");
02973 return TInetAddress();
02974 }
02975
02976 struct hostent *host_ptr;
02977 const char *hostname;
02978 int family;
02979 UInt_t iaddr;
02980
02981 if ((host_ptr = gethostbyaddr((const char *)&addr.sin_addr,
02982 sizeof(addr.sin_addr), AF_INET))) {
02983 memcpy(&iaddr, host_ptr->h_addr, host_ptr->h_length);
02984 hostname = host_ptr->h_name;
02985 family = host_ptr->h_addrtype;
02986 } else {
02987 memcpy(&iaddr, &addr.sin_addr, sizeof(addr.sin_addr));
02988 hostname = "????";
02989 family = AF_INET;
02990 }
02991
02992 return TInetAddress(hostname, ntohl(iaddr), family, ntohs(addr.sin_port));
02993 }
02994
02995
02996 TInetAddress TUnixSystem::GetPeerName(int sock)
02997 {
02998
02999
03000 struct sockaddr_in addr;
03001 #if defined(USE_SIZE_T)
03002 size_t len = sizeof(addr);
03003 #elif defined(USE_SOCKLEN_T)
03004 socklen_t len = sizeof(addr);
03005 #else
03006 int len = sizeof(addr);
03007 #endif
03008
03009 if (getpeername(sock, (struct sockaddr *)&addr, &len) == -1) {
03010 SysError("GetPeerName", "getpeername");
03011 return TInetAddress();
03012 }
03013
03014 struct hostent *host_ptr;
03015 const char *hostname;
03016 int family;
03017 UInt_t iaddr;
03018
03019 if ((host_ptr = gethostbyaddr((const char *)&addr.sin_addr,
03020 sizeof(addr.sin_addr), AF_INET))) {
03021 memcpy(&iaddr, host_ptr->h_addr, host_ptr->h_length);
03022 hostname = host_ptr->h_name;
03023 family = host_ptr->h_addrtype;
03024 } else {
03025 memcpy(&iaddr, &addr.sin_addr, sizeof(addr.sin_addr));
03026 hostname = "????";
03027 family = AF_INET;
03028 }
03029
03030 return TInetAddress(hostname, ntohl(iaddr), family, ntohs(addr.sin_port));
03031 }
03032
03033
03034 int TUnixSystem::GetServiceByName(const char *servicename)
03035 {
03036
03037
03038 struct servent *sp;
03039
03040 if ((sp = getservbyname(servicename, kProtocolName)) == 0) {
03041 Error("GetServiceByName", "no service \"%s\" with protocol \"%s\"\n",
03042 servicename, kProtocolName);
03043 return -1;
03044 }
03045 return ntohs(sp->s_port);
03046 }
03047
03048
03049 char *TUnixSystem::GetServiceByPort(int port)
03050 {
03051
03052
03053 struct servent *sp;
03054
03055 if ((sp = getservbyport(htons(port), kProtocolName)) == 0) {
03056
03057
03058 return Form("%d", port);
03059 }
03060 return sp->s_name;
03061 }
03062
03063
03064 int TUnixSystem::ConnectService(const char *servername, int port,
03065 int tcpwindowsize)
03066 {
03067
03068
03069 if (!strcmp(servername, "unix")) {
03070 return UnixUnixConnect(port);
03071 } else if (!gSystem->AccessPathName(servername) || servername[0] == '/') {
03072 return UnixUnixConnect(servername);
03073 }
03074 return UnixTcpConnect(servername, port, tcpwindowsize);
03075 }
03076
03077
03078 int TUnixSystem::OpenConnection(const char *server, int port, int tcpwindowsize)
03079 {
03080
03081
03082
03083
03084
03085
03086
03087 return ConnectService(server, port, tcpwindowsize);
03088 }
03089
03090
03091 int TUnixSystem::AnnounceTcpService(int port, Bool_t reuse, int backlog,
03092 int tcpwindowsize)
03093 {
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104 return UnixTcpService(port, reuse, backlog, tcpwindowsize);
03105 }
03106
03107
03108 int TUnixSystem::AnnounceUnixService(int port, int backlog)
03109 {
03110
03111
03112 return UnixUnixService(port, backlog);
03113 }
03114
03115
03116 int TUnixSystem::AnnounceUnixService(const char *sockpath, int backlog)
03117 {
03118
03119
03120 return UnixUnixService(sockpath, backlog);
03121 }
03122
03123
03124 int TUnixSystem::AcceptConnection(int sock)
03125 {
03126
03127
03128
03129
03130 int soc = -1;
03131
03132 while ((soc = ::accept(sock, 0, 0)) == -1 && GetErrno() == EINTR)
03133 ResetErrno();
03134
03135 if (soc == -1) {
03136 if (GetErrno() == EWOULDBLOCK)
03137 return -2;
03138 else {
03139 SysError("AcceptConnection", "accept");
03140 return -1;
03141 }
03142 }
03143
03144 return soc;
03145 }
03146
03147
03148 void TUnixSystem::CloseConnection(int sock, Bool_t force)
03149 {
03150
03151
03152 if (sock < 0) return;
03153
03154 #if !defined(R__AIX) || defined(_AIX41) || defined(_AIX43)
03155 if (force)
03156 ::shutdown(sock, 2);
03157 #endif
03158
03159 while (::close(sock) == -1 && GetErrno() == EINTR)
03160 ResetErrno();
03161 }
03162
03163
03164 int TUnixSystem::RecvBuf(int sock, void *buf, int length)
03165 {
03166
03167
03168
03169
03170 Int_t header;
03171
03172 if (UnixRecv(sock, &header, sizeof(header), 0) > 0) {
03173 int count = ntohl(header);
03174
03175 if (count > length) {
03176 Error("RecvBuf", "record header exceeds buffer size");
03177 return -1;
03178 } else if (count > 0) {
03179 if (UnixRecv(sock, buf, count, 0) < 0) {
03180 Error("RecvBuf", "cannot receive buffer");
03181 return -1;
03182 }
03183 }
03184 return count;
03185 }
03186 return -1;
03187 }
03188
03189
03190 int TUnixSystem::SendBuf(int sock, const void *buf, int length)
03191 {
03192
03193
03194
03195 Int_t header = htonl(length);
03196
03197 if (UnixSend(sock, &header, sizeof(header), 0) < 0) {
03198 Error("SendBuf", "cannot send header");
03199 return -1;
03200 }
03201 if (length > 0) {
03202 if (UnixSend(sock, buf, length, 0) < 0) {
03203 Error("SendBuf", "cannot send buffer");
03204 return -1;
03205 }
03206 }
03207 return length;
03208 }
03209
03210
03211 int TUnixSystem::RecvRaw(int sock, void *buf, int length, int opt)
03212 {
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222 int flag;
03223
03224 switch (opt) {
03225 case kDefault:
03226 flag = 0;
03227 break;
03228 case kOob:
03229 flag = MSG_OOB;
03230 break;
03231 case kPeek:
03232 flag = MSG_PEEK;
03233 break;
03234 case kDontBlock:
03235 flag = -1;
03236 break;
03237 default:
03238 flag = 0;
03239 break;
03240 }
03241
03242 int n;
03243 if ((n = UnixRecv(sock, buf, length, flag)) <= 0) {
03244 if (n == -1 && GetErrno() != EINTR)
03245 Error("RecvRaw", "cannot receive buffer");
03246 return n;
03247 }
03248 return n;
03249 }
03250
03251
03252 int TUnixSystem::SendRaw(int sock, const void *buf, int length, int opt)
03253 {
03254
03255
03256
03257
03258
03259 int flag;
03260
03261 switch (opt) {
03262 case kDefault:
03263 flag = 0;
03264 break;
03265 case kOob:
03266 flag = MSG_OOB;
03267 break;
03268 case kDontBlock:
03269 flag = -1;
03270 break;
03271 case kPeek:
03272 default:
03273 flag = 0;
03274 break;
03275 }
03276
03277 int n;
03278 if ((n = UnixSend(sock, buf, length, flag)) <= 0) {
03279 if (n == -1 && GetErrno() != EINTR)
03280 Error("SendRaw", "cannot send buffer");
03281 return n;
03282 }
03283 return n;
03284 }
03285
03286
03287 int TUnixSystem::SetSockOpt(int sock, int opt, int val)
03288 {
03289
03290
03291 if (sock < 0) return -1;
03292
03293 switch (opt) {
03294 case kSendBuffer:
03295 if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, sizeof(val)) == -1) {
03296 SysError("SetSockOpt", "setsockopt(SO_SNDBUF)");
03297 return -1;
03298 }
03299 break;
03300 case kRecvBuffer:
03301 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, sizeof(val)) == -1) {
03302 SysError("SetSockOpt", "setsockopt(SO_RCVBUF)");
03303 return -1;
03304 }
03305 break;
03306 case kOobInline:
03307 if (setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char*)&val, sizeof(val)) == -1) {
03308 SysError("SetSockOpt", "setsockopt(SO_OOBINLINE)");
03309 return -1;
03310 }
03311 break;
03312 case kKeepAlive:
03313 if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(val)) == -1) {
03314 SysError("SetSockOpt", "setsockopt(SO_KEEPALIVE)");
03315 return -1;
03316 }
03317 break;
03318 case kReuseAddr:
03319 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val)) == -1) {
03320 SysError("SetSockOpt", "setsockopt(SO_REUSEADDR)");
03321 return -1;
03322 }
03323 break;
03324 case kNoDelay:
03325 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(val)) == -1) {
03326 SysError("SetSockOpt", "setsockopt(TCP_NODELAY)");
03327 return -1;
03328 }
03329 break;
03330 case kNoBlock:
03331 if (ioctl(sock, FIONBIO, (char*)&val) == -1) {
03332 SysError("SetSockOpt", "ioctl(FIONBIO)");
03333 return -1;
03334 }
03335 break;
03336 case kProcessGroup:
03337 #ifndef R__WINGCC
03338 if (ioctl(sock, SIOCSPGRP, (char*)&val) == -1) {
03339 SysError("SetSockOpt", "ioctl(SIOCSPGRP)");
03340 return -1;
03341 }
03342 #else
03343 Error("SetSockOpt", "ioctl(SIOCGPGRP) not supported on cygwin/gcc");
03344 return -1;
03345 #endif
03346 break;
03347 case kAtMark:
03348 case kBytesToRead:
03349 default:
03350 Error("SetSockOpt", "illegal option (%d)", opt);
03351 return -1;
03352 }
03353 return 0;
03354 }
03355
03356
03357 int TUnixSystem::GetSockOpt(int sock, int opt, int *val)
03358 {
03359
03360
03361 if (sock < 0) return -1;
03362
03363 #if defined(USE_SOCKLEN_T) || defined(_AIX43)
03364 socklen_t optlen = sizeof(*val);
03365 #elif defined(USE_SIZE_T)
03366 size_t optlen = sizeof(*val);
03367 #else
03368 int optlen = sizeof(*val);
03369 #endif
03370
03371 switch (opt) {
03372 case kSendBuffer:
03373 if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)val, &optlen) == -1) {
03374 SysError("GetSockOpt", "getsockopt(SO_SNDBUF)");
03375 return -1;
03376 }
03377 break;
03378 case kRecvBuffer:
03379 if (getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)val, &optlen) == -1) {
03380 SysError("GetSockOpt", "getsockopt(SO_RCVBUF)");
03381 return -1;
03382 }
03383 break;
03384 case kOobInline:
03385 if (getsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char*)val, &optlen) == -1) {
03386 SysError("GetSockOpt", "getsockopt(SO_OOBINLINE)");
03387 return -1;
03388 }
03389 break;
03390 case kKeepAlive:
03391 if (getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)val, &optlen) == -1) {
03392 SysError("GetSockOpt", "getsockopt(SO_KEEPALIVE)");
03393 return -1;
03394 }
03395 break;
03396 case kReuseAddr:
03397 if (getsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)val, &optlen) == -1) {
03398 SysError("GetSockOpt", "getsockopt(SO_REUSEADDR)");
03399 return -1;
03400 }
03401 break;
03402 case kNoDelay:
03403 if (getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)val, &optlen) == -1) {
03404 SysError("GetSockOpt", "getsockopt(TCP_NODELAY)");
03405 return -1;
03406 }
03407 break;
03408 case kNoBlock:
03409 int flg;
03410 if ((flg = fcntl(sock, F_GETFL, 0)) == -1) {
03411 SysError("GetSockOpt", "fcntl(F_GETFL)");
03412 return -1;
03413 }
03414 *val = flg & O_NDELAY;
03415 break;
03416 case kProcessGroup:
03417 #if !defined(R__LYNXOS) && !defined(R__WINGCC)
03418 if (ioctl(sock, SIOCGPGRP, (char*)val) == -1) {
03419 SysError("GetSockOpt", "ioctl(SIOCGPGRP)");
03420 return -1;
03421 }
03422 #else
03423 Error("GetSockOpt", "ioctl(SIOCGPGRP) not supported on LynxOS and cygwin/gcc");
03424 return -1;
03425 #endif
03426 break;
03427 case kAtMark:
03428 #if !defined(R__LYNXOS)
03429 if (ioctl(sock, SIOCATMARK, (char*)val) == -1) {
03430 SysError("GetSockOpt", "ioctl(SIOCATMARK)");
03431 return -1;
03432 }
03433 #else
03434 Error("GetSockOpt", "ioctl(SIOCATMARK) not supported on LynxOS");
03435 return -1;
03436 #endif
03437 break;
03438 case kBytesToRead:
03439 #if !defined(R__LYNXOS)
03440 if (ioctl(sock, FIONREAD, (char*)val) == -1) {
03441 SysError("GetSockOpt", "ioctl(FIONREAD)");
03442 return -1;
03443 }
03444 #else
03445 Error("GetSockOpt", "ioctl(FIONREAD) not supported on LynxOS");
03446 return -1;
03447 #endif
03448 break;
03449 default:
03450 Error("GetSockOpt", "illegal option (%d)", opt);
03451 *val = 0;
03452 return -1;
03453 }
03454 return 0;
03455 }
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465 static struct Signalmap_t {
03466 int fCode;
03467 SigHandler_t fHandler;
03468 struct sigaction *fOldHandler;
03469 const char *fSigName;
03470 } gSignalMap[kMAXSIGNALS] = {
03471 { SIGBUS, 0, 0, "bus error" },
03472 { SIGSEGV, 0, 0, "segmentation violation" },
03473 { SIGSYS, 0, 0, "bad argument to system call" },
03474 { SIGPIPE, 0, 0, "write on a pipe with no one to read it" },
03475 { SIGILL, 0, 0, "illegal instruction" },
03476 { SIGQUIT, 0, 0, "quit" },
03477 { SIGINT, 0, 0, "interrupt" },
03478 { SIGWINCH, 0, 0, "window size change" },
03479 { SIGALRM, 0, 0, "alarm clock" },
03480 { SIGCHLD, 0, 0, "death of a child" },
03481 { SIGURG, 0, 0, "urgent data arrived on an I/O channel" },
03482 { SIGFPE, 0, 0, "floating point exception" },
03483 { SIGTERM, 0, 0, "termination signal" },
03484 { SIGUSR1, 0, 0, "user-defined signal 1" },
03485 { SIGUSR2, 0, 0, "user-defined signal 2" }
03486 };
03487
03488
03489
03490 static void sighandler(int sig)
03491 {
03492
03493
03494 for (int i= 0; i < kMAXSIGNALS; i++) {
03495 if (gSignalMap[i].fCode == sig) {
03496 (*gSignalMap[i].fHandler)((ESignals)i);
03497 return;
03498 }
03499 }
03500 }
03501
03502
03503 void TUnixSystem::UnixSignal(ESignals sig, SigHandler_t handler)
03504 {
03505
03506
03507 if (gSignalMap[sig].fHandler != handler) {
03508 struct sigaction sigact;
03509
03510 gSignalMap[sig].fHandler = handler;
03511 gSignalMap[sig].fOldHandler = new struct sigaction();
03512
03513 #if defined(R__SUN)
03514 sigact.sa_handler = (void (*)())sighandler;
03515 #elif defined(R__SOLARIS)
03516 sigact.sa_handler = sighandler;
03517 #elif defined(R__SGI) || defined(R__LYNXOS)
03518 # if defined(R__SGI64) || (__GNUG__>=3)
03519 sigact.sa_handler = sighandler;
03520 # else
03521 sigact.sa_handler = (void (*)(...))sighandler;
03522 # endif
03523 #else
03524 sigact.sa_handler = sighandler;
03525 #endif
03526 sigemptyset(&sigact.sa_mask);
03527 sigact.sa_flags = 0;
03528 #if defined(SA_RESTART)
03529 sigact.sa_flags |= SA_RESTART;
03530 #endif
03531 if (sigaction(gSignalMap[sig].fCode, &sigact,
03532 gSignalMap[sig].fOldHandler) < 0)
03533 ::SysError("TUnixSystem::UnixSignal", "sigaction");
03534 }
03535 }
03536
03537
03538 void TUnixSystem::UnixIgnoreSignal(ESignals sig, Bool_t ignore)
03539 {
03540
03541
03542
03543 static Bool_t ignoreSig[kMAXSIGNALS] = { kFALSE };
03544 static struct sigaction oldsigact[kMAXSIGNALS];
03545
03546 if (ignore != ignoreSig[sig]) {
03547 ignoreSig[sig] = ignore;
03548 if (ignore) {
03549 struct sigaction sigact;
03550 #if defined(R__SUN)
03551 sigact.sa_handler = (void (*)())SIG_IGN;
03552 #elif defined(R__SOLARIS)
03553 sigact.sa_handler = (void (*)(int))SIG_IGN;
03554 #else
03555 sigact.sa_handler = SIG_IGN;
03556 #endif
03557 sigemptyset(&sigact.sa_mask);
03558 sigact.sa_flags = 0;
03559 if (sigaction(gSignalMap[sig].fCode, &sigact, &oldsigact[sig]) < 0)
03560 ::SysError("TUnixSystem::UnixIgnoreSignal", "sigaction");
03561 } else {
03562 if (sigaction(gSignalMap[sig].fCode, &oldsigact[sig], 0) < 0)
03563 ::SysError("TUnixSystem::UnixIgnoreSignal", "sigaction");
03564 }
03565 }
03566 }
03567
03568
03569 void TUnixSystem::UnixSigAlarmInterruptsSyscalls(Bool_t set)
03570 {
03571
03572
03573
03574
03575
03576
03577
03578 if (gSignalMap[kSigAlarm].fHandler) {
03579 struct sigaction sigact;
03580 #if defined(R__SUN)
03581 sigact.sa_handler = (void (*)())sighandler;
03582 #elif defined(R__SOLARIS)
03583 sigact.sa_handler = sighandler;
03584 #elif defined(R__SGI) || defined(R__LYNXOS)
03585 # if defined(R__SGI64) || (__GNUG__>=3)
03586 sigact.sa_handler = sighandler;
03587 # else
03588 sigact.sa_handler = (void (*)(...))sighandler;
03589 # endif
03590 #else
03591 sigact.sa_handler = sighandler;
03592 #endif
03593 sigemptyset(&sigact.sa_mask);
03594 sigact.sa_flags = 0;
03595 if (set) {
03596 #if defined(SA_INTERRUPT) // SunOS
03597 sigact.sa_flags |= SA_INTERRUPT;
03598 #endif
03599 } else {
03600 #if defined(SA_RESTART)
03601 sigact.sa_flags |= SA_RESTART;
03602 #endif
03603 }
03604 if (sigaction(gSignalMap[kSigAlarm].fCode, &sigact, 0) < 0)
03605 ::SysError("TUnixSystem::UnixSigAlarmInterruptsSyscalls", "sigaction");
03606 }
03607 }
03608
03609
03610 const char *TUnixSystem::UnixSigname(ESignals sig)
03611 {
03612
03613
03614 return gSignalMap[sig].fSigName;
03615 }
03616
03617
03618 void TUnixSystem::UnixResetSignal(ESignals sig)
03619 {
03620
03621
03622 if (gSignalMap[sig].fOldHandler) {
03623
03624 if (sigaction(gSignalMap[sig].fCode, gSignalMap[sig].fOldHandler, 0) < 0)
03625 ::SysError("TUnixSystem::UnixSignal", "sigaction");
03626 delete gSignalMap[sig].fOldHandler;
03627 gSignalMap[sig].fOldHandler = 0;
03628 gSignalMap[sig].fHandler = 0;
03629 }
03630 }
03631
03632
03633 void TUnixSystem::UnixResetSignals()
03634 {
03635
03636
03637 for (int sig = 0; sig < kMAXSIGNALS; sig++)
03638 UnixResetSignal((ESignals)sig);
03639 }
03640
03641
03642
03643
03644 Long64_t TUnixSystem::UnixNow()
03645 {
03646
03647
03648 static time_t jan95 = 0;
03649 if (!jan95) {
03650 struct tm tp;
03651 tp.tm_year = 95;
03652 tp.tm_mon = 0;
03653 tp.tm_mday = 1;
03654 tp.tm_hour = 0;
03655 tp.tm_min = 0;
03656 tp.tm_sec = 0;
03657 tp.tm_isdst = -1;
03658
03659 jan95 = mktime(&tp);
03660 if ((int)jan95 == -1) {
03661 ::SysError("TUnixSystem::UnixNow", "error converting 950001 0:00 to time_t");
03662 return 0;
03663 }
03664 }
03665
03666 struct timeval t;
03667 gettimeofday(&t, 0);
03668 return Long64_t(t.tv_sec-(Long_t)jan95)*1000 + t.tv_usec/1000;
03669 }
03670
03671
03672 int TUnixSystem::UnixSetitimer(Long_t ms)
03673 {
03674
03675
03676 struct itimerval itv;
03677 itv.it_value.tv_sec = 0;
03678 itv.it_value.tv_usec = 0;
03679 itv.it_interval.tv_sec = 0;
03680 itv.it_interval.tv_usec = 0;
03681 if (ms > 0) {
03682 itv.it_value.tv_sec = time_t(ms / 1000);
03683 itv.it_value.tv_usec = time_t((ms % 1000) * 1000);
03684 }
03685 int st = setitimer(ITIMER_REAL, &itv, 0);
03686 if (st == -1)
03687 ::SysError("TUnixSystem::UnixSetitimer", "setitimer");
03688 return st;
03689 }
03690
03691
03692
03693
03694 int TUnixSystem::UnixSelect(Int_t nfds, TFdSet *readready, TFdSet *writeready,
03695 Long_t timeout)
03696 {
03697
03698
03699
03700
03701
03702
03703 int retcode;
03704
03705 #if defined(R__HPUX) && defined(R__B64)
03706 fd_set frd;
03707 fd_set fwr;
03708 FD_ZERO(&frd);
03709 FD_ZERO(&fwr);
03710 for (int i = 0; i < nfds; i++) {
03711 if (readready && readready->IsSet(i)) FD_SET(i, &frd);
03712 if (writeready && writeready->IsSet(i)) FD_SET(i, &fwr);
03713 }
03714 fd_set *rd = (readready) ? &frd : 0;
03715 fd_set *wr = (writeready) ? &fwr : 0;
03716 #else
03717 fd_set *rd = (readready) ? (fd_set*)readready->GetBits() : 0;
03718 fd_set *wr = (writeready) ? (fd_set*)writeready->GetBits() : 0;
03719 #endif
03720
03721 if (timeout >= 0) {
03722 struct timeval tv;
03723 tv.tv_sec = Int_t(timeout / 1000);
03724 tv.tv_usec = (timeout % 1000) * 1000;
03725 retcode = select(nfds, rd, wr, 0, &tv);
03726 } else {
03727 retcode = select(nfds, rd, wr, 0, 0);
03728 }
03729 if (retcode == -1) {
03730 if (GetErrno() == EINTR) {
03731 ResetErrno();
03732 return -2;
03733 }
03734 if (GetErrno() == EBADF)
03735 return -3;
03736 return -1;
03737 }
03738
03739 #if defined(R__HPUX) && defined(R__B64)
03740 if (rd) readready->Zero();
03741 if (wr) writeready->Zero();
03742 for (int i = 0; i < nfds; i++) {
03743 if (rd && FD_ISSET(i, rd)) readready->Set(i);
03744 if (wr && FD_ISSET(i, wr)) writeready->Set(i);
03745 }
03746 #endif
03747
03748 return retcode;
03749 }
03750
03751
03752
03753
03754 const char *TUnixSystem::UnixHomedirectory(const char *name)
03755 {
03756
03757
03758 static char path[kMAXPATHLEN], mydir[kMAXPATHLEN] = { '\0' };
03759 struct passwd *pw;
03760
03761 if (name) {
03762 pw = getpwnam(name);
03763 if (pw) {
03764 strncpy(path, pw->pw_dir, kMAXPATHLEN-1);
03765 path[sizeof(path)-1] = '\0';
03766 return path;
03767 }
03768 } else {
03769 if (mydir[0])
03770 return mydir;
03771 pw = getpwuid(getuid());
03772 if (pw) {
03773 strncpy(mydir, pw->pw_dir, kMAXPATHLEN-1);
03774 mydir[sizeof(mydir)-1] = '\0';
03775 return mydir;
03776 }
03777 }
03778 return 0;
03779 }
03780
03781
03782 int TUnixSystem::UnixMakedir(const char *dir)
03783 {
03784
03785
03786
03787
03788 return ::mkdir(StripOffProto(dir, "file:"), 0755);
03789 }
03790
03791
03792 void *TUnixSystem::UnixOpendir(const char *dir)
03793 {
03794
03795
03796 struct stat finfo;
03797
03798 const char *edir = StripOffProto(dir, "file:");
03799
03800 if (stat(edir, &finfo) < 0)
03801 return 0;
03802
03803 if (!S_ISDIR(finfo.st_mode))
03804 return 0;
03805
03806 return (void*) opendir(edir);
03807 }
03808
03809 #if defined(_POSIX_SOURCE)
03810
03811
03812 # define REAL_DIR_ENTRY(dp) 1
03813 #else
03814 # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
03815 #endif
03816
03817
03818 const char *TUnixSystem::UnixGetdirentry(void *dirp1)
03819 {
03820
03821
03822 DIR *dirp = (DIR*)dirp1;
03823 #ifdef HAS_DIRENT
03824 struct dirent *dp;
03825 #else
03826 struct direct *dp;
03827 #endif
03828
03829 if (dirp) {
03830 for (;;) {
03831 dp = readdir(dirp);
03832 if (dp == 0)
03833 return 0;
03834 if (REAL_DIR_ENTRY(dp))
03835 return dp->d_name;
03836 }
03837 }
03838 return 0;
03839 }
03840
03841
03842
03843
03844 int TUnixSystem::UnixFilestat(const char *fpath, FileStat_t &buf)
03845 {
03846
03847
03848
03849
03850
03851 const char *path = StripOffProto(fpath, "file:");
03852 buf.fIsLink = kFALSE;
03853
03854 #if defined(R__SEEK64)
03855 struct stat64 sbuf;
03856 if (path && lstat64(path, &sbuf) == 0) {
03857 #else
03858 struct stat sbuf;
03859 if (path && lstat(path, &sbuf) == 0) {
03860 #endif
03861 buf.fIsLink = S_ISLNK(sbuf.st_mode);
03862 if (buf.fIsLink) {
03863 #if defined(R__SEEK64)
03864 if (stat64(path, &sbuf) == -1) {
03865 #else
03866 if (stat(path, &sbuf) == -1) {
03867 #endif
03868 return 1;
03869 }
03870 }
03871 buf.fDev = sbuf.st_dev;
03872 buf.fIno = sbuf.st_ino;
03873 buf.fMode = sbuf.st_mode;
03874 buf.fUid = sbuf.st_uid;
03875 buf.fGid = sbuf.st_gid;
03876 buf.fSize = sbuf.st_size;
03877 buf.fMtime = sbuf.st_mtime;
03878
03879 return 0;
03880 }
03881 return 1;
03882 }
03883
03884
03885 int TUnixSystem::UnixFSstat(const char *path, Long_t *id, Long_t *bsize,
03886 Long_t *blocks, Long_t *bfree)
03887 {
03888
03889
03890
03891
03892
03893
03894
03895
03896 struct statfs statfsbuf;
03897 #if defined(R__SGI) || (defined(R__SOLARIS) && !defined(R__LINUX))
03898 if (statfs(path, &statfsbuf, sizeof(struct statfs), 0) == 0) {
03899 *id = statfsbuf.f_fstyp;
03900 *bsize = statfsbuf.f_bsize;
03901 *blocks = statfsbuf.f_blocks;
03902 *bfree = statfsbuf.f_bfree;
03903 #else
03904 if (statfs((char*)path, &statfsbuf) == 0) {
03905 #ifdef R__OBSD
03906
03907
03908
03909
03910 if (!strcmp(statfsbuf.f_fstypename, MOUNT_FFS) ||
03911 !strcmp(statfsbuf.f_fstypename, MOUNT_MFS))
03912 *id = 0x11954;
03913 else if (!strcmp(statfsbuf.f_fstypename, MOUNT_NFS))
03914 *id = 0x6969;
03915 else if (!strcmp(statfsbuf.f_fstypename, MOUNT_MSDOS))
03916 *id = 0x4d44;
03917 else if (!strcmp(statfsbuf.f_fstypename, MOUNT_PROCFS))
03918 *id = 0x9fa0;
03919 else if (!strcmp(statfsbuf.f_fstypename, MOUNT_EXT2FS))
03920 *id = 0xef53;
03921 else if (!strcmp(statfsbuf.f_fstypename, MOUNT_CD9660))
03922 *id = 0x9660;
03923 else if (!strcmp(statfsbuf.f_fstypename, MOUNT_NCPFS))
03924 *id = 0x6969;
03925 else
03926 *id = -1;
03927 #else
03928 *id = statfsbuf.f_type;
03929 #endif
03930 *bsize = statfsbuf.f_bsize;
03931 *blocks = statfsbuf.f_blocks;
03932 *bfree = statfsbuf.f_bavail;
03933 #endif
03934 return 0;
03935 }
03936 return 1;
03937 }
03938
03939
03940 int TUnixSystem::UnixWaitchild()
03941 {
03942
03943
03944 int status;
03945 return (int) waitpid(0, &status, WNOHANG);
03946 }
03947
03948
03949
03950
03951 int TUnixSystem::UnixTcpConnect(const char *hostname, int port,
03952 int tcpwindowsize)
03953 {
03954
03955
03956
03957
03958
03959
03960 short sport;
03961 struct servent *sp;
03962
03963 if ((sp = getservbyport(htons(port), kProtocolName)))
03964 sport = sp->s_port;
03965 else
03966 sport = htons(port);
03967
03968 TInetAddress addr = gSystem->GetHostByName(hostname);
03969 if (!addr.IsValid()) return -1;
03970 UInt_t adr = htonl(addr.GetAddress());
03971
03972 struct sockaddr_in server;
03973 memset(&server, 0, sizeof(server));
03974 memcpy(&server.sin_addr, &adr, sizeof(adr));
03975 server.sin_family = addr.GetFamily();
03976 server.sin_port = sport;
03977
03978
03979 int sock;
03980 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
03981 ::SysError("TUnixSystem::UnixTcpConnect", "socket (%s:%d)",
03982 hostname, port);
03983 return -1;
03984 }
03985
03986 if (tcpwindowsize > 0) {
03987 gSystem->SetSockOpt(sock, kRecvBuffer, tcpwindowsize);
03988 gSystem->SetSockOpt(sock, kSendBuffer, tcpwindowsize);
03989 }
03990
03991 while (connect(sock, (struct sockaddr*) &server, sizeof(server)) == -1) {
03992 if (GetErrno() == EINTR)
03993 ResetErrno();
03994 else {
03995 ::SysError("TUnixSystem::UnixTcpConnect", "connect (%s:%d)",
03996 hostname, port);
03997 close(sock);
03998 return -1;
03999 }
04000 }
04001 return sock;
04002 }
04003
04004
04005 int TUnixSystem::UnixUnixConnect(int port)
04006 {
04007
04008
04009 return UnixUnixConnect(TString::Format("%s/%d", kServerPath, port));
04010 }
04011
04012
04013 int TUnixSystem::UnixUnixConnect(const char *sockpath)
04014 {
04015
04016
04017 if (!sockpath || strlen(sockpath) <= 0) {
04018 ::SysError("TUnixSystem::UnixUnixConnect", "socket path undefined");
04019 return -1;
04020 }
04021
04022 int sock;
04023 struct sockaddr_un unserver;
04024 unserver.sun_family = AF_UNIX;
04025
04026 if (strlen(sockpath) > sizeof(unserver.sun_path)-1) {
04027 ::Error("TUnixSystem::UnixUnixConnect", "socket path %s, longer than max allowed length (%u)",
04028 sockpath, (UInt_t)sizeof(unserver.sun_path)-1);
04029 return -1;
04030 }
04031 strcpy(unserver.sun_path, sockpath);
04032
04033
04034 if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
04035 ::SysError("TUnixSystem::UnixUnixConnect", "socket");
04036 return -1;
04037 }
04038
04039 while (connect(sock, (struct sockaddr*) &unserver, strlen(unserver.sun_path)+2) == -1) {
04040 if (GetErrno() == EINTR)
04041 ResetErrno();
04042 else {
04043 ::SysError("TUnixSystem::UnixUnixConnect", "connect");
04044 close(sock);
04045 return -1;
04046 }
04047 }
04048 return sock;
04049 }
04050
04051
04052 int TUnixSystem::UnixTcpService(int port, Bool_t reuse, int backlog,
04053 int tcpwindowsize)
04054 {
04055
04056
04057
04058
04059
04060
04061
04062
04063
04064
04065
04066 const short kSOCKET_MINPORT = 5000, kSOCKET_MAXPORT = 15000;
04067 short sport, tryport = kSOCKET_MINPORT;
04068 struct servent *sp;
04069
04070 if (port == 0 && reuse) {
04071 ::Error("TUnixSystem::UnixTcpService", "cannot do a port scan while reuse is true");
04072 return -1;
04073 }
04074
04075 if ((sp = getservbyport(htons(port), kProtocolName)))
04076 sport = sp->s_port;
04077 else
04078 sport = htons(port);
04079
04080
04081 int sock;
04082 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
04083 ::SysError("TUnixSystem::UnixTcpService", "socket");
04084 return -1;
04085 }
04086
04087 if (reuse)
04088 gSystem->SetSockOpt(sock, kReuseAddr, 1);
04089
04090 if (tcpwindowsize > 0) {
04091 gSystem->SetSockOpt(sock, kRecvBuffer, tcpwindowsize);
04092 gSystem->SetSockOpt(sock, kSendBuffer, tcpwindowsize);
04093 }
04094
04095 struct sockaddr_in inserver;
04096 memset(&inserver, 0, sizeof(inserver));
04097 inserver.sin_family = AF_INET;
04098 inserver.sin_addr.s_addr = htonl(INADDR_ANY);
04099 inserver.sin_port = sport;
04100
04101
04102 if (port > 0) {
04103 if (bind(sock, (struct sockaddr*) &inserver, sizeof(inserver))) {
04104 ::SysError("TUnixSystem::UnixTcpService", "bind");
04105 return -2;
04106 }
04107 } else {
04108 int bret;
04109 do {
04110 inserver.sin_port = htons(tryport++);
04111 bret = bind(sock, (struct sockaddr*) &inserver, sizeof(inserver));
04112 } while (bret < 0 && GetErrno() == EADDRINUSE && tryport < kSOCKET_MAXPORT);
04113 if (bret < 0) {
04114 ::SysError("TUnixSystem::UnixTcpService", "bind (port scan)");
04115 return -2;
04116 }
04117 }
04118
04119
04120 if (listen(sock, backlog)) {
04121 ::SysError("TUnixSystem::UnixTcpService", "listen");
04122 return -3;
04123 }
04124
04125 return sock;
04126 }
04127
04128
04129 int TUnixSystem::UnixUnixService(int port, int backlog)
04130 {
04131
04132
04133
04134 int oldumask;
04135
04136
04137 oldumask = umask(0);
04138 ::mkdir(kServerPath, 0777);
04139 umask(oldumask);
04140
04141
04142 TString sockpath;
04143 sockpath.Form("%s/%d", kServerPath, port);
04144
04145
04146 unlink(sockpath.Data());
04147
04148 return UnixUnixService(sockpath, backlog);
04149 }
04150
04151
04152 int TUnixSystem::UnixUnixService(const char *sockpath, int backlog)
04153 {
04154
04155
04156
04157 if (!sockpath || strlen(sockpath) <= 0) {
04158 ::SysError("TUnixSystem::UnixUnixService", "socket path undefined");
04159 return -1;
04160 }
04161
04162 struct sockaddr_un unserver;
04163 int sock;
04164
04165
04166 memset(&unserver, 0, sizeof(unserver));
04167 unserver.sun_family = AF_UNIX;
04168
04169 if (strlen(sockpath) > sizeof(unserver.sun_path)-1) {
04170 ::Error("TUnixSystem::UnixUnixService", "socket path %s, longer than max allowed length (%u)",
04171 sockpath, (UInt_t)sizeof(unserver.sun_path)-1);
04172 return -1;
04173 }
04174 strcpy(unserver.sun_path, sockpath);
04175
04176
04177 if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
04178 ::SysError("TUnixSystem::UnixUnixService", "socket");
04179 return -1;
04180 }
04181
04182 if (bind(sock, (struct sockaddr*) &unserver, strlen(unserver.sun_path)+2)) {
04183 ::SysError("TUnixSystem::UnixUnixService", "bind");
04184 return -1;
04185 }
04186
04187
04188 if (listen(sock, backlog)) {
04189 ::SysError("TUnixSystem::UnixUnixService", "listen");
04190 return -1;
04191 }
04192
04193 return sock;
04194 }
04195
04196
04197 int TUnixSystem::UnixRecv(int sock, void *buffer, int length, int flag)
04198 {
04199
04200
04201
04202
04203
04204
04205 ResetErrno();
04206
04207 if (sock < 0) return -1;
04208
04209 int once = 0;
04210 if (flag == -1) {
04211 flag = 0;
04212 once = 1;
04213 }
04214 if (flag == MSG_PEEK)
04215 once = 1;
04216
04217 int n, nrecv = 0;
04218 char *buf = (char *)buffer;
04219
04220 for (n = 0; n < length; n += nrecv) {
04221 if ((nrecv = recv(sock, buf+n, length-n, flag)) <= 0) {
04222 if (nrecv == 0)
04223 break;
04224 if (flag == MSG_OOB) {
04225 if (GetErrno() == EWOULDBLOCK)
04226 return -2;
04227 else if (GetErrno() == EINVAL)
04228 return -3;
04229 }
04230 if (GetErrno() == EWOULDBLOCK)
04231 return -4;
04232 else {
04233 if (GetErrno() != EINTR)
04234 ::SysError("TUnixSystem::UnixRecv", "recv");
04235 if (GetErrno() == EPIPE || GetErrno() == ECONNRESET)
04236 return -5;
04237 else
04238 return -1;
04239 }
04240 }
04241 if (once)
04242 return nrecv;
04243 }
04244 return n;
04245 }
04246
04247
04248 int TUnixSystem::UnixSend(int sock, const void *buffer, int length, int flag)
04249 {
04250
04251
04252
04253
04254
04255 if (sock < 0) return -1;
04256
04257 int once = 0;
04258 if (flag == -1) {
04259 flag = 0;
04260 once = 1;
04261 }
04262
04263 int n, nsent = 0;
04264 const char *buf = (const char *)buffer;
04265
04266 for (n = 0; n < length; n += nsent) {
04267 if ((nsent = send(sock, buf+n, length-n, flag)) <= 0) {
04268 if (nsent == 0)
04269 break;
04270 if (GetErrno() == EWOULDBLOCK)
04271 return -4;
04272 else {
04273 if (GetErrno() != EINTR)
04274 ::SysError("TUnixSystem::UnixSend", "send");
04275 if (GetErrno() == EPIPE || GetErrno() == ECONNRESET)
04276 return -5;
04277 else
04278 return -1;
04279 }
04280 }
04281 if (once)
04282 return nsent;
04283 }
04284 return n;
04285 }
04286
04287
04288
04289
04290 static const char *DynamicPath(const char *newpath = 0, Bool_t reset = kFALSE)
04291 {
04292
04293
04294 static TString dynpath;
04295 static Bool_t initialized = kFALSE;
04296
04297 if (newpath) {
04298 dynpath = newpath;
04299 } else if (reset || !initialized) {
04300 initialized = kTRUE;
04301 TString rdynpath = gEnv->GetValue("Root.DynamicPath", (char*)0);
04302 rdynpath.ReplaceAll(": ", ":");
04303 if (rdynpath.IsNull()) {
04304 #ifdef ROOTLIBDIR
04305 rdynpath = ".:"; rdynpath += ROOTLIBDIR;
04306 #else
04307 rdynpath = ".:"; rdynpath += gRootDir; rdynpath += "/lib";
04308 #endif
04309 }
04310 TString ldpath;
04311 #if defined (R__AIX)
04312 ldpath = gSystem->Getenv("LIBPATH");
04313 #elif defined(R__HPUX)
04314 ldpath = gSystem->Getenv("SHLIB_PATH");
04315 #elif defined(R__MACOSX)
04316 ldpath = gSystem->Getenv("DYLD_LIBRARY_PATH");
04317 if (!ldpath.IsNull())
04318 ldpath += ":";
04319 ldpath += gSystem->Getenv("LD_LIBRARY_PATH");
04320 #else
04321 ldpath = gSystem->Getenv("LD_LIBRARY_PATH");
04322 #endif
04323 if (ldpath.IsNull())
04324 dynpath = rdynpath;
04325 else {
04326 dynpath = ldpath; dynpath += ":"; dynpath += rdynpath;
04327 }
04328
04329 #ifdef ROOTLIBDIR
04330 if (!dynpath.Contains(ROOTLIBDIR)) {
04331 dynpath += ":"; dynpath += ROOTLIBDIR;
04332 }
04333 #else
04334 if (!dynpath.Contains(TString::Format("%s/lib", gRootDir))) {
04335 dynpath += ":"; dynpath += gRootDir; dynpath += "/lib";
04336 }
04337 #endif
04338 dynpath += ":"; dynpath += gInterpreter->GetSTLIncludePath();
04339 }
04340 return dynpath;
04341 }
04342
04343
04344 void TUnixSystem::AddDynamicPath(const char *path)
04345 {
04346
04347
04348 if (path) {
04349 TString oldpath = DynamicPath(0, kFALSE);
04350 oldpath.Append(":");
04351 oldpath.Append(path);
04352 DynamicPath(oldpath);
04353 }
04354 }
04355
04356
04357 const char *TUnixSystem::GetDynamicPath()
04358 {
04359
04360
04361 return DynamicPath(0, kFALSE);
04362 }
04363
04364
04365 void TUnixSystem::SetDynamicPath(const char *path)
04366 {
04367
04368
04369
04370
04371 if (!path)
04372 DynamicPath(0, kTRUE);
04373 else
04374 DynamicPath(path);
04375 }
04376
04377
04378 char *TUnixSystem::DynamicPathName(const char *lib, Bool_t quiet)
04379 {
04380
04381
04382
04383
04384
04385 char *name;
04386
04387 int ext = 0, len = strlen(lib);
04388 if (len > 3 && (!strcmp(lib+len-3, ".sl") ||
04389 !strcmp(lib+len-3, ".dl") ||
04390 !strcmp(lib+len-4, ".dll")||
04391 !strcmp(lib+len-4, ".DLL")||
04392 !strcmp(lib+len-3, ".so") ||
04393 !strcmp(lib+len-2, ".a"))) {
04394 name = gSystem->Which(GetDynamicPath(), lib, kReadPermission);
04395 ext = 1;
04396 } else {
04397 TString fname;
04398 fname.Form("%s.so", lib);
04399 name = gSystem->Which(GetDynamicPath(), fname, kReadPermission);
04400 if (!name) {
04401 fname.Form("%s.dll", lib);
04402 name = gSystem->Which(GetDynamicPath(), fname, kReadPermission);
04403 if (!name) {
04404 fname.Form("%s.sl", lib);
04405 name = gSystem->Which(GetDynamicPath(), fname, kReadPermission);
04406 if (!name) {
04407 fname.Form("%s.dl", lib);
04408 name = gSystem->Which(GetDynamicPath(), fname, kReadPermission);
04409 if (!name) {
04410 fname.Form("%s.a", lib);
04411 name = gSystem->Which(GetDynamicPath(), fname, kReadPermission);
04412 }
04413 }
04414 }
04415 }
04416 }
04417
04418 if (!name && !quiet) {
04419 if (ext)
04420 Error("DynamicPathName",
04421 "%s does not exist in %s", lib, GetDynamicPath());
04422 else
04423 Error("DynamicPathName",
04424 "%s[.so | .sl | .dl | .a | .dll] does not exist in %s", lib, GetDynamicPath());
04425 }
04426
04427 return name;
04428 }
04429
04430
04431 void *TUnixSystem::FindDynLib(const char *lib)
04432 {
04433
04434
04435
04436 #ifdef R__HPUX
04437 const char *path;
04438
04439 if ((path = gSystem->DynamicPathName(lib))) {
04440
04441 struct shl_descriptor *desc;
04442 int index = 0;
04443 while (shl_get(index++, &desc) == 0)
04444 if (!strcmp(path, desc->filename))
04445 return desc->handle;
04446 }
04447 #endif
04448
04449 if (lib) { }
04450
04451 return 0;
04452 }
04453
04454
04455 int TUnixSystem::UnixDynLoad(const char *lib)
04456 {
04457
04458
04459
04460
04461 const char *path;
04462
04463 if ((path = gSystem->DynamicPathName(lib))) {
04464 #if defined(R__HPUX)
04465 #if !defined(__STDCPP__)
04466 shl_t handle = cxxshl_load(path, BIND_IMMEDIATE | BIND_NONFATAL, 0L);
04467 #else
04468 shl_t handle = shl_load(path, BIND_IMMEDIATE | BIND_NONFATAL, 0L);
04469 #endif
04470 if (handle != 0) return 0;
04471 #else
04472 if (path) { }
04473 ::Error("TUnixSystem::UnixDynLoad", "not yet implemented for this platform");
04474 return -1;
04475 #endif
04476 }
04477 return -1;
04478 }
04479
04480
04481 Func_t TUnixSystem::UnixDynFindSymbol(const char *lib, const char *entry)
04482 {
04483
04484
04485
04486 #if defined(R__HPUX) && !defined(R__GNU)
04487 shl_t handle;
04488
04489 if (handle = (shl_t)FindDynLib(lib)) {
04490 Func_t addr = 0;
04491 if (shl_findsym(&handle, entry, TYPE_PROCEDURE, addr) == -1)
04492 ::SysError("TUnixSystem::UnixDynFindSymbol", "shl_findsym");
04493 return addr;
04494 }
04495 return 0;
04496 #else
04497 if (lib || entry) { }
04498
04499
04500 return 0;
04501 #endif
04502 }
04503
04504
04505 void TUnixSystem::UnixDynListSymbols(const char *lib, const char *regexp)
04506 {
04507
04508
04509
04510 #if defined(R__HPUX) && !defined(R__GNU)
04511 shl_t handle;
04512
04513 if (handle = (shl_t)FindDynLib(lib)) {
04514 struct shl_symbol *symbols;
04515 int nsym = shl_getsymbols(handle, TYPE_PROCEDURE,
04516 EXPORT_SYMBOLS|NO_VALUES, (void *(*)())malloc,
04517 &symbols);
04518 if (nsym != -1) {
04519 if (nsym > 0) {
04520 int cnt = 0;
04521 TRegexp *re = 0;
04522 if (regexp && strlen(regexp)) re = new TRegexp(regexp, kTRUE);
04523 Printf("");
04524 Printf("Functions exported by library %s", gSystem->DynamicPathName(lib));
04525 Printf("=========================================================");
04526 for (int i = 0; i < nsym; i++)
04527 if (symbols[i].type == TYPE_PROCEDURE) {
04528 cnt++;
04529 char *dsym = cplus_demangle(symbols[i].name,
04530 DMGL_PARAMS|DMGL_ANSI|DMGL_ARM);
04531 if (re) {
04532 TString s = dsym;
04533 if (s.Index(*re) != kNPOS) Printf("%s", dsym);
04534 } else
04535 Printf("%s", dsym);
04536 free(dsym);
04537 }
04538 Printf("---------------------------------------------------------");
04539 Printf("%d exported functions", cnt);
04540 Printf("=========================================================");
04541 delete re;
04542 }
04543 free(symbols);
04544 }
04545 }
04546 #endif
04547 if (lib || regexp) { }
04548 }
04549
04550
04551 void TUnixSystem::UnixDynListLibs(const char *lib)
04552 {
04553
04554
04555 #if defined(R__HPUX) && !defined(R__GNU)
04556 TRegexp *re = 0;
04557 if (lib && strlen(lib)) re = new TRegexp(lib, kTRUE);
04558 struct shl_descriptor *desc;
04559 int index = 0;
04560
04561 Printf("");
04562 Printf("Loaded shared libraries");
04563 Printf("=======================");
04564
04565 while (shl_get(index++, &desc) == 0)
04566 if (re) {
04567 TString s = desc->filename;
04568 if (s.Index(*re) != kNPOS) Printf("%s", desc->filename);
04569 } else
04570 Printf("%s", desc->filename);
04571 Printf("-----------------------");
04572 Printf("%d libraries loaded", index-1);
04573 Printf("=======================");
04574 delete re;
04575 #else
04576 if (lib) { }
04577 #endif
04578 }
04579
04580
04581 void TUnixSystem::UnixDynUnload(const char *lib)
04582 {
04583
04584
04585 #if defined(R__HPUX)
04586 shl_t handle;
04587
04588 if (handle = (shl_t)FindDynLib(lib))
04589 #if !defined(__STDCPP__)
04590 if (cxxshl_unload(handle) == -1)
04591 #else
04592 if (shl_unload(handle) == -1)
04593 #endif
04594 ::SysError("TUnixSystem::UnixDynUnload", "could not unload library %s", lib);
04595 #else
04596 if (lib) { }
04597
04598 ::Error("TUnixSystem::UnixDynUnload", "not yet implemented for this platform");
04599 #endif
04600 }
04601
04602
04603 int TUnixSystem::ReadUtmpFile()
04604 {
04605
04606
04607 FILE *utmp;
04608 struct stat file_stats;
04609 size_t n_read, size;
04610
04611 R__LOCKGUARD2(gSystemMutex);
04612
04613 gUtmpContents = 0;
04614
04615 utmp = fopen(UTMP_FILE, "r");
04616 if (!utmp)
04617 return 0;
04618
04619 fstat(fileno(utmp), &file_stats);
04620 size = file_stats.st_size;
04621 if (size <= 0) {
04622 fclose(utmp);
04623 return 0;
04624 }
04625
04626 gUtmpContents = (STRUCT_UTMP *) malloc(size);
04627 if (!gUtmpContents) {
04628 fclose(utmp);
04629 return 0;
04630 }
04631
04632 n_read = fread(gUtmpContents, 1, size, utmp);
04633 if (!ferror(utmp)) {
04634 if (fclose(utmp) != EOF && n_read == size)
04635 return size / sizeof(STRUCT_UTMP);
04636 } else
04637 fclose(utmp);
04638
04639 free(gUtmpContents);
04640 gUtmpContents = 0;
04641 return 0;
04642 }
04643
04644
04645 void *TUnixSystem::SearchUtmpEntry(int n, const char *tty)
04646 {
04647
04648
04649 STRUCT_UTMP *ue = gUtmpContents;
04650
04651 while (n--) {
04652 if (ue->ut_name[0] && !strncmp(tty, ue->ut_line, sizeof(ue->ut_line)))
04653 return ue;
04654 ue++;
04655 }
04656 return 0;
04657 }
04658
04659
04660
04661 #if defined(R__MACOSX)
04662 #include <sys/resource.h>
04663 #include <mach/mach.h>
04664 #include <mach/mach_error.h>
04665
04666
04667 static void GetDarwinSysInfo(SysInfo_t *sysinfo)
04668 {
04669
04670
04671 FILE *p = gSystem->OpenPipe("sysctl -n kern.ostype hw.model hw.ncpu hw.cpufrequency "
04672 "hw.busfrequency hw.l2cachesize hw.physmem", "r");
04673 TString s;
04674 s.Gets(p);
04675 sysinfo->fOS = s;
04676 s.Gets(p);
04677 sysinfo->fModel = s;
04678 s.Gets(p);
04679 sysinfo->fCpus = s.Atoi();
04680 s.Gets(p);
04681 Long64_t t = s.Atoll();
04682 sysinfo->fCpuSpeed = Int_t(t / 1000000);
04683 s.Gets(p);
04684 t = s.Atoll();
04685 sysinfo->fBusSpeed = Int_t(t / 1000000);
04686 s.Gets(p);
04687 sysinfo->fL2Cache = s.Atoi() / 1024;
04688 s.Gets(p);
04689 t = s.Atoll();
04690 sysinfo->fPhysRam = Int_t(t / 1024 / 1024);
04691 gSystem->ClosePipe(p);
04692 p = gSystem->OpenPipe("hostinfo", "r");
04693 while (s.Gets(p)) {
04694 if (s.BeginsWith("Processor type: ")) {
04695 TPRegexp("Processor type: ([^ ]+).*").Substitute(s, "$1");
04696 sysinfo->fCpuType = s;
04697 }
04698 }
04699 gSystem->ClosePipe(p);
04700 }
04701
04702
04703 static void ReadDarwinCpu(long *ticks)
04704 {
04705
04706
04707 mach_msg_type_number_t count;
04708 kern_return_t kr;
04709 host_cpu_load_info_data_t cpu;
04710
04711 ticks[0] = ticks[1] = ticks[2] = ticks[3] = 0;
04712
04713 count = HOST_CPU_LOAD_INFO_COUNT;
04714 kr = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&cpu, &count);
04715 if (kr != KERN_SUCCESS) {
04716 ::Error("TUnixSystem::ReadDarwinCpu", "host_statistics: %s", mach_error_string(kr));
04717 } else {
04718 ticks[0] = cpu.cpu_ticks[CPU_STATE_USER];
04719 ticks[1] = cpu.cpu_ticks[CPU_STATE_SYSTEM];
04720 ticks[2] = cpu.cpu_ticks[CPU_STATE_IDLE];
04721 ticks[3] = cpu.cpu_ticks[CPU_STATE_NICE];
04722 }
04723 }
04724
04725
04726 static void GetDarwinCpuInfo(CpuInfo_t *cpuinfo, Int_t sampleTime)
04727 {
04728
04729
04730
04731 Double_t avg[3];
04732 if (getloadavg(avg, sizeof(avg)) < 0) {
04733 ::Error("TUnixSystem::GetDarwinCpuInfo", "getloadavg failed");
04734 } else {
04735 cpuinfo->fLoad1m = (Float_t)avg[0];
04736 cpuinfo->fLoad5m = (Float_t)avg[1];
04737 cpuinfo->fLoad15m = (Float_t)avg[2];
04738 }
04739
04740 Long_t cpu_ticks1[4], cpu_ticks2[4];
04741 ReadDarwinCpu(cpu_ticks1);
04742 gSystem->Sleep(sampleTime);
04743 ReadDarwinCpu(cpu_ticks2);
04744
04745 Long_t userticks = (cpu_ticks2[0] + cpu_ticks2[3]) -
04746 (cpu_ticks1[0] + cpu_ticks1[3]);
04747 Long_t systicks = cpu_ticks2[1] - cpu_ticks1[1];
04748 Long_t idleticks = cpu_ticks2[2] - cpu_ticks1[2];
04749 if (userticks < 0) userticks = 0;
04750 if (systicks < 0) systicks = 0;
04751 if (idleticks < 0) idleticks = 0;
04752 Long_t totalticks = userticks + systicks + idleticks;
04753 if (totalticks) {
04754 cpuinfo->fUser = ((Float_t)(100 * userticks)) / ((Float_t)totalticks);
04755 cpuinfo->fSys = ((Float_t)(100 * systicks)) / ((Float_t)totalticks);
04756 cpuinfo->fTotal = cpuinfo->fUser + cpuinfo->fSys;
04757 cpuinfo->fIdle = ((Float_t)(100 * idleticks)) / ((Float_t)totalticks);
04758 }
04759 }
04760
04761
04762 static void GetDarwinMemInfo(MemInfo_t *meminfo)
04763 {
04764
04765
04766 static Int_t pshift = 0;
04767 static DIR *dirp;
04768 vm_statistics_data_t vm_info;
04769 mach_msg_type_number_t count;
04770 kern_return_t kr;
04771 struct dirent *dp;
04772 Long64_t total, used, free, swap_total, swap_used;
04773
04774 count = HOST_VM_INFO_COUNT;
04775 kr = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_info, &count);
04776 if (kr != KERN_SUCCESS) {
04777 ::Error("TUnixSystem::GetDarwinMemInfo", "host_statistics: %s", mach_error_string(kr));
04778 return;
04779 }
04780 if (pshift == 0) {
04781 for (int psize = getpagesize(); psize > 1; psize >>= 1)
04782 pshift++;
04783 }
04784
04785 used = (Long64_t)(vm_info.active_count + vm_info.inactive_count + vm_info.wire_count) << pshift;
04786 free = (Long64_t)(vm_info.free_count) << pshift;
04787 total = (Long64_t)(vm_info.active_count + vm_info.inactive_count + vm_info.free_count + vm_info.wire_count) << pshift;
04788
04789
04790 swap_used = vm_info.pageouts << pshift;
04791
04792
04793 dirp = opendir("/private/var/vm");
04794 if (!dirp)
04795 return;
04796
04797 swap_total = 0;
04798 while ((dp = readdir(dirp)) != 0) {
04799 struct stat sb;
04800 char fname [MAXNAMLEN];
04801 if (strncmp(dp->d_name, "swapfile", 8))
04802 continue;
04803 strlcpy(fname, "/private/var/vm/",MAXNAMLEN);
04804 strlcat (fname, dp->d_name,MAXNAMLEN);
04805 if (stat(fname, &sb) < 0)
04806 continue;
04807 swap_total += sb.st_size;
04808 }
04809 closedir(dirp);
04810
04811 meminfo->fMemTotal = (Int_t) (total >> 20);
04812 meminfo->fMemUsed = (Int_t) (used >> 20);
04813 meminfo->fMemFree = (Int_t) (free >> 20);
04814 meminfo->fSwapTotal = (Int_t) (swap_total >> 20);
04815 meminfo->fSwapUsed = (Int_t) (swap_used >> 20);
04816 meminfo->fSwapFree = meminfo->fSwapTotal - meminfo->fSwapUsed;
04817 }
04818
04819
04820 static void GetDarwinProcInfo(ProcInfo_t *procinfo)
04821 {
04822
04823
04824 #ifdef _LP64
04825 #define vm_region vm_region_64
04826 #endif
04827
04828
04829 #define GLOBAL_SHARED_TEXT_SEGMENT 0x90000000U
04830 #define GLOBAL_SHARED_DATA_SEGMENT 0xA0000000U
04831 #define SHARED_TEXT_REGION_SIZE 0x10000000
04832 #define SHARED_DATA_REGION_SIZE 0x10000000
04833
04834 struct rusage ru;
04835 if (getrusage(RUSAGE_SELF, &ru) < 0) {
04836 ::SysError("TUnixSystem::GetDarwinProcInfo", "getrusage failed");
04837 } else {
04838 procinfo->fCpuUser = (Float_t)(ru.ru_utime.tv_sec) +
04839 ((Float_t)(ru.ru_utime.tv_usec) / 1000000.);
04840 procinfo->fCpuSys = (Float_t)(ru.ru_stime.tv_sec) +
04841 ((Float_t)(ru.ru_stime.tv_usec) / 1000000.);
04842 }
04843
04844 task_basic_info_data_t ti;
04845 mach_msg_type_number_t count;
04846 kern_return_t kr;
04847
04848 task_t a_task = mach_task_self();
04849
04850 count = TASK_BASIC_INFO_COUNT;
04851 kr = task_info(a_task, TASK_BASIC_INFO, (task_info_t)&ti, &count);
04852 if (kr != KERN_SUCCESS) {
04853 ::Error("TUnixSystem::GetDarwinProcInfo", "task_info: %s", mach_error_string(kr));
04854 } else {
04855
04856
04857
04858 mach_port_t object_name;
04859 vm_address_t address;
04860 vm_region_top_info_data_t info;
04861 vm_size_t vsize, rsize, size;
04862 rsize = ti.resident_size;
04863 vsize = ti.virtual_size;
04864 for (address = 0; ; address += size) {
04865
04866 count = VM_REGION_TOP_INFO_COUNT;
04867 if (vm_region(a_task, &address, &size,
04868 VM_REGION_TOP_INFO, (vm_region_info_t)&info, &count,
04869 &object_name) != KERN_SUCCESS) {
04870
04871 break;
04872 }
04873
04874 if (address >= GLOBAL_SHARED_TEXT_SEGMENT &&
04875 address < (GLOBAL_SHARED_DATA_SEGMENT + SHARED_DATA_REGION_SIZE)) {
04876
04877
04878
04879
04880 if (info.share_mode == SM_EMPTY) {
04881 vm_region_basic_info_data_64_t b_info;
04882 count = VM_REGION_BASIC_INFO_COUNT_64;
04883 if (vm_region_64(a_task, &address,
04884 &size, VM_REGION_BASIC_INFO,
04885 (vm_region_info_t)&b_info, &count,
04886 &object_name) != KERN_SUCCESS) {
04887 break;
04888 }
04889
04890 if (b_info.reserved) {
04891 vsize -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
04892 break;
04893 }
04894 }
04895 }
04896 }
04897
04898 procinfo->fMemResident = (Long_t)(rsize / 1024);
04899 procinfo->fMemVirtual = (Long_t)(vsize / 1024);
04900 }
04901 }
04902 #endif
04903
04904 #if defined(R__LINUX)
04905
04906 static void GetLinuxSysInfo(SysInfo_t *sysinfo)
04907 {
04908
04909
04910 TString s;
04911 FILE *f = fopen("/proc/cpuinfo", "r");
04912 while (s.Gets(f)) {
04913 if (s.BeginsWith("model name")) {
04914 TPRegexp("^.+: *(.*$)").Substitute(s, "$1");
04915 sysinfo->fModel = s;
04916 }
04917 if (s.BeginsWith("cpu MHz")) {
04918 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
04919 sysinfo->fCpuSpeed = s.Atoi();
04920 }
04921 if (s.BeginsWith("cache size")) {
04922 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
04923 sysinfo->fL2Cache = s.Atoi();
04924 }
04925 if (s.BeginsWith("processor")) {
04926 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
04927 sysinfo->fCpus = s.Atoi();
04928 sysinfo->fCpus++;
04929 }
04930 }
04931 fclose(f);
04932
04933 f = fopen("/proc/meminfo", "r");
04934 while (s.Gets(f)) {
04935 if (s.BeginsWith("MemTotal")) {
04936 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
04937 sysinfo->fPhysRam = (s.Atoi() / 1024);
04938 break;
04939 }
04940 }
04941 fclose(f);
04942
04943 f = gSystem->OpenPipe("uname -s -p", "r");
04944 s.Gets(f);
04945 Ssiz_t from = 0;
04946 s.Tokenize(sysinfo->fOS, from);
04947 s.Tokenize(sysinfo->fCpuType, from);
04948 gSystem->ClosePipe(f);
04949 }
04950
04951
04952 static void ReadLinuxCpu(long *ticks)
04953 {
04954
04955
04956 ticks[0] = ticks[1] = ticks[2] = ticks[3] = 0;
04957
04958 TString s;
04959 FILE *f = fopen("/proc/stat", "r");
04960 s.Gets(f);
04961
04962 sscanf(s.Data(), "%*s %ld %ld %ld %ld", &ticks[0], &ticks[3], &ticks[1], &ticks[2]);
04963 fclose(f);
04964 }
04965
04966
04967 static void GetLinuxCpuInfo(CpuInfo_t *cpuinfo, Int_t sampleTime)
04968 {
04969
04970
04971
04972 Double_t avg[3] = { -1., -1., -1. };
04973 #ifndef R__WINGCC
04974 if (getloadavg(avg, sizeof(avg)) < 0) {
04975 ::Error("TUnixSystem::GetLinuxCpuInfo", "getloadavg failed");
04976 } else
04977 #endif
04978 {
04979 cpuinfo->fLoad1m = (Float_t)avg[0];
04980 cpuinfo->fLoad5m = (Float_t)avg[1];
04981 cpuinfo->fLoad15m = (Float_t)avg[2];
04982 }
04983
04984 Long_t cpu_ticks1[4], cpu_ticks2[4];
04985 ReadLinuxCpu(cpu_ticks1);
04986 gSystem->Sleep(sampleTime);
04987 ReadLinuxCpu(cpu_ticks2);
04988
04989 Long_t userticks = (cpu_ticks2[0] + cpu_ticks2[3]) -
04990 (cpu_ticks1[0] + cpu_ticks1[3]);
04991 Long_t systicks = cpu_ticks2[1] - cpu_ticks1[1];
04992 Long_t idleticks = cpu_ticks2[2] - cpu_ticks1[2];
04993 if (userticks < 0) userticks = 0;
04994 if (systicks < 0) systicks = 0;
04995 if (idleticks < 0) idleticks = 0;
04996 Long_t totalticks = userticks + systicks + idleticks;
04997 if (totalticks) {
04998 cpuinfo->fUser = ((Float_t)(100 * userticks)) / ((Float_t)totalticks);
04999 cpuinfo->fSys = ((Float_t)(100 * systicks)) / ((Float_t)totalticks);
05000 cpuinfo->fTotal = cpuinfo->fUser + cpuinfo->fSys;
05001 cpuinfo->fIdle = ((Float_t)(100 * idleticks)) / ((Float_t)totalticks);
05002 }
05003 }
05004
05005
05006 static void GetLinuxMemInfo(MemInfo_t *meminfo)
05007 {
05008
05009
05010 TString s;
05011 FILE *f = fopen("/proc/meminfo", "r");
05012 while (s.Gets(f)) {
05013 if (s.BeginsWith("MemTotal")) {
05014 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
05015 meminfo->fMemTotal = (s.Atoi() / 1024);
05016 }
05017 if (s.BeginsWith("MemFree")) {
05018 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
05019 meminfo->fMemFree = (s.Atoi() / 1024);
05020 }
05021 if (s.BeginsWith("SwapTotal")) {
05022 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
05023 meminfo->fSwapTotal = (s.Atoi() / 1024);
05024 }
05025 if (s.BeginsWith("SwapFree")) {
05026 TPRegexp("^.+: *([^ ]+).*").Substitute(s, "$1");
05027 meminfo->fSwapFree = (s.Atoi() / 1024);
05028 }
05029 }
05030 fclose(f);
05031
05032 meminfo->fMemUsed = meminfo->fMemTotal - meminfo->fMemFree;
05033 meminfo->fSwapUsed = meminfo->fSwapTotal - meminfo->fSwapFree;
05034 }
05035
05036
05037 static void GetLinuxProcInfo(ProcInfo_t *procinfo)
05038 {
05039
05040
05041 struct rusage ru;
05042 if (getrusage(RUSAGE_SELF, &ru) < 0) {
05043 ::SysError("TUnixSystem::GetLinuxProcInfo", "getrusage failed");
05044 } else {
05045 procinfo->fCpuUser = (Float_t)(ru.ru_utime.tv_sec) +
05046 ((Float_t)(ru.ru_utime.tv_usec) / 1000000.);
05047 procinfo->fCpuSys = (Float_t)(ru.ru_stime.tv_sec) +
05048 ((Float_t)(ru.ru_stime.tv_usec) / 1000000.);
05049 }
05050
05051 procinfo->fMemVirtual = -1;
05052 procinfo->fMemResident = -1;
05053 TString s;
05054 FILE *f = fopen(TString::Format("/proc/%d/statm", gSystem->GetPid()), "r");
05055 if (f) {
05056 s.Gets(f);
05057 fclose(f);
05058 Long_t total, rss;
05059 sscanf(s.Data(), "%ld %ld", &total, &rss);
05060 procinfo->fMemVirtual = total * (getpagesize() / 1024);
05061 procinfo->fMemResident = rss * (getpagesize() / 1024);
05062 }
05063 }
05064 #endif
05065
05066
05067 int TUnixSystem::GetSysInfo(SysInfo_t *info) const
05068 {
05069
05070
05071
05072
05073 if (!info) return -1;
05074
05075 static SysInfo_t sysinfo;
05076
05077 if (!sysinfo.fCpus) {
05078 #if defined(R__MACOSX)
05079 GetDarwinSysInfo(&sysinfo);
05080 #elif defined(R__LINUX)
05081 GetLinuxSysInfo(&sysinfo);
05082 #endif
05083 }
05084
05085 *info = sysinfo;
05086
05087 return 0;
05088 }
05089
05090
05091 int TUnixSystem::GetCpuInfo(CpuInfo_t *info, Int_t sampleTime) const
05092 {
05093
05094
05095
05096
05097 if (!info) return -1;
05098
05099 #if defined(R__MACOSX)
05100 GetDarwinCpuInfo(info, sampleTime);
05101 #elif defined(R__LINUX)
05102 GetLinuxCpuInfo(info, sampleTime);
05103 #endif
05104
05105 return 0;
05106 }
05107
05108
05109 int TUnixSystem::GetMemInfo(MemInfo_t *info) const
05110 {
05111
05112
05113
05114 if (!info) return -1;
05115
05116 #if defined(R__MACOSX)
05117 GetDarwinMemInfo(info);
05118 #elif defined(R__LINUX)
05119 GetLinuxMemInfo(info);
05120 #endif
05121
05122 return 0;
05123 }
05124
05125
05126 int TUnixSystem::GetProcInfo(ProcInfo_t *info) const
05127 {
05128
05129
05130
05131 if (!info) return -1;
05132
05133 #if defined(R__MACOSX)
05134 GetDarwinProcInfo(info);
05135 #elif defined(R__LINUX)
05136 GetLinuxProcInfo(info);
05137 #endif
05138
05139 return 0;
05140 }