rootx.cxx

Go to the documentation of this file.
00001 // @(#)root/rootx:$Id: rootx.cxx 36277 2010-10-11 08:26:26Z rdm $
00002 // Author: Fons Rademakers   19/02/98
00003 
00004 //////////////////////////////////////////////////////////////////////////
00005 //                                                                      //
00006 // Rootx                                                                //
00007 //                                                                      //
00008 // Rootx is a small front-end program that starts the main ROOT module. //
00009 // This program is called "root" in the $ROOTSYS/bin directory and the  //
00010 // real ROOT executable is now called "root.exe" (formerly "root").     //
00011 // Rootx puts up a splash screen giving some info about the current     //
00012 // version of ROOT and, more importanly, it sets up the required        //
00013 // LD_LIBRARY_PATH, SHLIB_PATH and LIBPATH environment variables        //
00014 // (depending on the platform).                                         //
00015 //                                                                      //
00016 //////////////////////////////////////////////////////////////////////////
00017 
00018 #include "RConfigure.h"
00019 #include "Rtypes.h"
00020 
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <unistd.h>
00024 #include <string.h>
00025 #include <signal.h>
00026 #include <sys/wait.h>
00027 #include <sys/stat.h>
00028 #include <errno.h>
00029 #include <netdb.h>
00030 #include <sys/socket.h>
00031 #include <string>
00032 #ifdef __APPLE__
00033 #include <AvailabilityMacros.h>
00034 #include <mach-o/dyld.h>
00035 #endif
00036 
00037 #if defined(__sgi) || defined(__sun)
00038 #define HAVE_UTMPX_H
00039 #define UTMP_NO_ADDR
00040 #endif
00041 
00042 #if defined(MAC_OS_X_VERSION_10_5)
00043 #   define HAVE_UTMPX_H
00044 #   define UTMP_NO_ADDR
00045 #   ifndef ut_user
00046 #      define ut_user ut_name
00047 #   endif
00048 #endif
00049 
00050 #if (defined(__alpha) && !defined(__linux)) || defined(_AIX) || \
00051     defined(__FreeBSD__) || defined(__Lynx__) || defined(__OpenBSD__) || \
00052     (defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_5))
00053 #define UTMP_NO_ADDR
00054 #endif
00055 
00056 #ifdef __sun
00057 #   ifndef _REENTRANT
00058 #      if __SUNPRO_CC > 0x420
00059 #         define GLOBAL_ERRNO
00060 #      endif
00061 #   endif
00062 #endif
00063 
00064 # ifdef HAVE_UTMPX_H
00065 # include <utmpx.h>
00066 # define STRUCT_UTMP struct utmpx
00067 # else
00068 # if defined(__linux) && defined(__powerpc) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 90)
00069    extern "C" {
00070 # endif
00071 # include <utmp.h>
00072 # define STRUCT_UTMP struct utmp
00073 # endif
00074 
00075 #if !defined(UTMP_FILE) && defined(_PATH_UTMP)      // 4.4BSD
00076 #define UTMP_FILE _PATH_UTMP
00077 #endif
00078 #if defined(UTMPX_FILE)                             // Solaris, SysVr4
00079 #undef  UTMP_FILE
00080 #define UTMP_FILE UTMPX_FILE
00081 #endif
00082 #ifndef UTMP_FILE
00083 #define UTMP_FILE "/etc/utmp"
00084 #endif
00085 
00086 #if defined(__CYGWIN__) && defined(__GNUC__)
00087 #define ROOTBINARY "root_exe.exe"
00088 #else
00089 #define ROOTBINARY "root.exe"
00090 #endif
00091 
00092 extern void PopupLogo(bool);
00093 extern void WaitLogo();
00094 extern void PopdownLogo();
00095 extern void CloseDisplay();
00096 
00097 
00098 static STRUCT_UTMP *gUtmpContents;
00099 static bool gNoLogo = false;
00100 const  int  kMAXPATHLEN = 8192;
00101 
00102 
00103 static int GetErrno()
00104 {
00105 #ifdef GLOBAL_ERRNO
00106    return ::errno;
00107 #else
00108    return errno;
00109 #endif
00110 }
00111 
00112 static void ResetErrno()
00113 {
00114 #ifdef GLOBAL_ERRNO
00115    ::errno = 0;
00116 #else
00117    errno = 0;
00118 #endif
00119 }
00120 
00121 static int ReadUtmp()
00122 {
00123    FILE  *utmp;
00124    struct stat file_stats;
00125    size_t n_read, size;
00126 
00127    gUtmpContents = 0;
00128 
00129    utmp = fopen(UTMP_FILE, "r");
00130    if (!utmp)
00131       return 0;
00132 
00133    fstat(fileno(utmp), &file_stats);
00134    size = file_stats.st_size;
00135    if (size <= 0) {
00136       fclose(utmp);
00137       return 0;
00138    }
00139 
00140    gUtmpContents = (STRUCT_UTMP *) malloc(size);
00141    if (!gUtmpContents) {
00142       fclose(utmp);
00143       return 0;
00144    }
00145 
00146    n_read = fread(gUtmpContents, 1, size, utmp);
00147    if (!ferror(utmp)) {
00148       if (fclose(utmp) != EOF && n_read == size)
00149          return size / sizeof(STRUCT_UTMP);
00150    } else
00151       fclose(utmp);
00152 
00153    free(gUtmpContents);
00154    gUtmpContents = 0;
00155    return 0;
00156 }
00157 
00158 static STRUCT_UTMP *SearchEntry(int n, const char *tty)
00159 {
00160    STRUCT_UTMP *ue = gUtmpContents;
00161 
00162    while (n--) {
00163       if (ue->ut_name[0] && !strncmp(tty, ue->ut_line, sizeof(ue->ut_line)))
00164          return ue;
00165       ue++;
00166    }
00167    return 0;
00168 }
00169 
00170 static const char *GetExePath()
00171 {
00172    static std::string exepath;
00173    if (exepath == "") {
00174 #ifdef __APPLE__
00175       exepath = _dyld_get_image_name(0);
00176 #endif
00177 #ifdef __linux
00178       char linkname[64];      // /proc/<pid>/exe
00179       char buf[kMAXPATHLEN];  // exe path name
00180       pid_t pid;
00181 
00182       // get our pid and build the name of the link in /proc
00183       pid = getpid();
00184       snprintf(linkname,64, "/proc/%i/exe", pid);
00185       int ret = readlink(linkname, buf, kMAXPATHLEN);
00186       if (ret > 0 && ret < kMAXPATHLEN) {
00187          buf[ret] = 0;
00188          exepath = buf;
00189       }
00190 #endif
00191    }
00192    return exepath.c_str();
00193 }
00194 
00195 static void SetRootSys()
00196 {
00197    const char *exepath = GetExePath();
00198    if (exepath && *exepath) {
00199       int l1 = strlen(exepath)+1;
00200       char *ep = new char[l1];
00201       strlcpy(ep, exepath, l1);
00202       char *s;
00203       if ((s = strrchr(ep, '/'))) {
00204          *s = 0;
00205          if ((s = strrchr(ep, '/'))) {
00206             *s = 0;
00207             int l2 = strlen(ep) + 10;
00208             char *env = new char[l2];
00209             snprintf(env, l2, "ROOTSYS=%s", ep);
00210             putenv(env);
00211          }
00212       }
00213       delete [] ep;
00214    }
00215 }
00216 
00217 static void SetDisplay()
00218 {
00219    // Set DISPLAY environment variable.
00220 
00221    if (!getenv("DISPLAY")) {
00222       char *tty = ttyname(0);  // device user is logged in on
00223       if (tty) {
00224          tty += 5;             // remove "/dev/"
00225          STRUCT_UTMP *utmp_entry = SearchEntry(ReadUtmp(), tty);
00226          if (utmp_entry) {
00227             char *display = new char[sizeof(utmp_entry->ut_host) + 15];
00228             char *host = new char[sizeof(utmp_entry->ut_host) + 1];
00229             strncpy(host, utmp_entry->ut_host, sizeof(utmp_entry->ut_host));
00230             host[sizeof(utmp_entry->ut_host)] = 0;
00231             if (host[0]) {
00232                if (strchr(host, ':')) {
00233                   sprintf(display, "DISPLAY=%s", host);
00234                   fprintf(stderr, "*** DISPLAY not set, setting it to %s\n",
00235                           host);
00236                } else {
00237                   sprintf(display, "DISPLAY=%s:0.0", host);
00238                   fprintf(stderr, "*** DISPLAY not set, setting it to %s:0.0\n",
00239                           host);
00240                }
00241                putenv(display);
00242 #ifndef UTMP_NO_ADDR
00243             } else if (utmp_entry->ut_addr) {
00244                struct hostent *he;
00245                if ((he = gethostbyaddr((const char*)&utmp_entry->ut_addr,
00246                                        sizeof(utmp_entry->ut_addr), AF_INET))) {
00247                   sprintf(display, "DISPLAY=%s:0.0", he->h_name);
00248                   fprintf(stderr, "*** DISPLAY not set, setting it to %s:0.0\n",
00249                           he->h_name);
00250                   putenv(display);
00251                }
00252 #endif
00253             }
00254             delete [] host;
00255             // display cannot be deleted otherwise the env var is deleted too
00256          }
00257          free(gUtmpContents);
00258       }
00259    }
00260 }
00261 
00262 static void SetLibraryPath()
00263 {
00264 #ifndef ROOTLIBDIR
00265    // Set library path for the different platforms.
00266 
00267    char *msg;
00268 
00269 #  if defined(__hpux)  || defined(_HIUX_SOURCE)
00270    if (getenv("SHLIB_PATH")) {
00271       msg = new char [strlen(getenv("ROOTSYS"))+strlen(getenv("SHLIB_PATH"))+100];
00272       sprintf(msg, "SHLIB_PATH=%s/lib:%s", getenv("ROOTSYS"),
00273                                            getenv("SHLIB_PATH"));
00274    } else {
00275       msg = new char [strlen(getenv("ROOTSYS"))+100];
00276       sprintf(msg, "SHLIB_PATH=%s/lib", getenv("ROOTSYS"));
00277    }
00278 #  elif defined(_AIX)
00279    if (getenv("LIBPATH")) {
00280       msg = new char [strlen(getenv("ROOTSYS"))+strlen(getenv("LIBPATH"))+100];
00281       sprintf(msg, "LIBPATH=%s/lib:%s", getenv("ROOTSYS"),
00282                                         getenv("LIBPATH"));
00283    } else {
00284       msg = new char [strlen(getenv("ROOTSYS"))+100];
00285       sprintf(msg, "LIBPATH=%s/lib:/lib:/usr/lib", getenv("ROOTSYS"));
00286    }
00287 #  elif defined(__APPLE__)
00288    if (getenv("DYLD_LIBRARY_PATH")) {
00289       msg = new char [strlen(getenv("ROOTSYS"))+strlen(getenv("DYLD_LIBRARY_PATH"))+100];
00290       sprintf(msg, "DYLD_LIBRARY_PATH=%s/lib:%s", getenv("ROOTSYS"),
00291                                                   getenv("DYLD_LIBRARY_PATH"));
00292    } else {
00293       msg = new char [strlen(getenv("ROOTSYS"))+100];
00294       sprintf(msg, "DYLD_LIBRARY_PATH=%s/lib", getenv("ROOTSYS"));
00295    }
00296 #  else
00297    if (getenv("LD_LIBRARY_PATH")) {
00298       msg = new char [strlen(getenv("ROOTSYS"))+strlen(getenv("LD_LIBRARY_PATH"))+100];
00299       sprintf(msg, "LD_LIBRARY_PATH=%s/lib:%s", getenv("ROOTSYS"),
00300                                                 getenv("LD_LIBRARY_PATH"));
00301    } else {
00302       msg = new char [strlen(getenv("ROOTSYS"))+100];
00303 #  if defined(__sun)
00304       sprintf(msg, "LD_LIBRARY_PATH=%s/lib:/usr/dt/lib", getenv("ROOTSYS"));
00305 #  else
00306       sprintf(msg, "LD_LIBRARY_PATH=%s/lib", getenv("ROOTSYS"));
00307 #  endif
00308    }
00309 #  endif
00310    putenv(msg);
00311 #endif
00312 }
00313 
00314 extern "C" {
00315    static void SigUsr1(int);
00316 }
00317 
00318 static void SigUsr1(int)
00319 {
00320    // When we get SIGUSR1 from child (i.e. ROOT) then pop down logo.
00321 
00322    if (!gNoLogo)
00323       PopdownLogo();
00324 }
00325 
00326 static void WaitChild(int childpid)
00327 {
00328    // Wait till child (i.e. ROOT) is finished.
00329 
00330    int status;
00331 
00332    do {
00333       while (waitpid(childpid, &status, WUNTRACED) < 0) {
00334          if (GetErrno() != EINTR)
00335             break;
00336          ResetErrno();
00337       }
00338 
00339       if (WIFEXITED(status))
00340          exit(WEXITSTATUS(status));
00341 
00342       if (WIFSIGNALED(status))
00343          exit(WTERMSIG(status));
00344 
00345       if (WIFSTOPPED(status)) {         // child got ctlr-Z
00346          raise(SIGTSTP);                // stop also parent
00347          kill(childpid, SIGCONT);       // if parent wakes up, wake up child
00348       }
00349    } while (WIFSTOPPED(status));
00350 
00351    exit(0);
00352 }
00353 
00354 static void PrintUsage(char *pname)
00355 {
00356    // This is a copy of the text in TApplication::GetOptions().
00357 
00358    fprintf(stderr, "Usage: %s [-l] [-b] [-n] [-q] [dir] [[file:]data.root] [file1.C ... fileN.C]\n", pname);
00359    fprintf(stderr, "Options:\n");
00360    fprintf(stderr, "  -b : run in batch mode without graphics\n");
00361    fprintf(stderr, "  -n : do not execute logon and logoff macros as specified in .rootrc\n");
00362    fprintf(stderr, "  -q : exit after processing command line macro files\n");
00363    fprintf(stderr, "  -l : do not show splash screen\n");
00364    fprintf(stderr, "  -x : exit on exception\n");
00365    fprintf(stderr, " dir : if dir is a valid directory cd to it before executing\n");
00366    fprintf(stderr, "\n");
00367    fprintf(stderr, "  -?       : print usage\n");
00368    fprintf(stderr, "  -h       : print usage\n");
00369    fprintf(stderr, "  --help   : print usage\n");
00370    fprintf(stderr, "  -config  : print ./configure options\n");
00371    fprintf(stderr, "  -memstat : run with memory usage monitoring\n");
00372    fprintf(stderr, "\n");
00373 }
00374 
00375 int main(int argc, char **argv)
00376 {
00377    char **argvv;
00378    char  arg0[kMAXPATHLEN];
00379 
00380 #ifndef ROOTPREFIX
00381    // Try to set ROOTSYS depending on pathname of the executable
00382    SetRootSys();
00383 
00384    if (!getenv("ROOTSYS")) {
00385       fprintf(stderr, "%s: ROOTSYS not set. Set it before trying to run %s.\n",
00386               argv[0], argv[0]);
00387       return 1;
00388    }
00389 #endif
00390 
00391    // In batch mode don't show splash screen, idem for no logo mode,
00392    // in about mode show always splash screen
00393    bool batch = false, about = false;
00394    int i;
00395    for (i = 1; i < argc; i++) {
00396       if (!strcmp(argv[i], "-?") || !strncmp(argv[i], "-h", 2) ||
00397           !strncmp(argv[i], "--help", 6)) {
00398          PrintUsage(argv[0]);
00399          return 1;
00400       }
00401       if (!strcmp(argv[i], "-b"))      batch   = true;
00402       if (!strcmp(argv[i], "-l"))      gNoLogo = true;
00403       if (!strcmp(argv[i], "-ll"))     gNoLogo = true;
00404       if (!strcmp(argv[i], "-a"))      about   = true;
00405       if (!strcmp(argv[i], "-config")) gNoLogo = true;
00406    }
00407    if (batch)
00408       gNoLogo = true;
00409    if (about) {
00410       batch   = false;
00411       gNoLogo = false;
00412    }
00413 
00414    if (!batch) {
00415       SetDisplay();
00416       if (!getenv("DISPLAY")) {
00417          fprintf(stderr, "%s: can't figure out DISPLAY, set it manually\n", argv[0]);
00418          fprintf(stderr, "In case you run a remote ssh session, restart your ssh session with:\n");
00419          fprintf(stderr, "=========>  ssh -Y\n");
00420          return 1;
00421       }
00422       if (about) {
00423          PopupLogo(true);
00424          WaitLogo();
00425          return 0;
00426       } else if (!gNoLogo)
00427          PopupLogo(false);
00428    }
00429 
00430    // Ignore SIGINT and SIGQUIT. Install handler for SIGUSR1.
00431 
00432    struct sigaction ignore, handle, saveintr, savequit, saveusr1;
00433 
00434 #if defined(__sun) && !defined(__i386) && !defined(__SVR4)
00435    ignore.sa_handler = (void (*)())SIG_IGN;
00436 #elif defined(__sun) && defined(__SVR4)
00437    ignore.sa_handler = (void (*)(int))SIG_IGN;
00438 #else
00439    ignore.sa_handler = SIG_IGN;
00440 #endif
00441    sigemptyset(&ignore.sa_mask);
00442    ignore.sa_flags = 0;
00443    handle = ignore;
00444 #if defined(__sun) && !defined(__i386) && !defined(__SVR4)
00445    handle.sa_handler = (void (*)())SigUsr1;
00446 #elif defined(__sun) && defined(__SVR4)
00447    handle.sa_handler = SigUsr1;
00448 #elif (defined(__sgi) && !defined(__KCC)) || defined(__Lynx__)
00449 #   if defined(IRIX64) || (__GNUG__>=3)
00450    handle.sa_handler = SigUsr1;
00451 #   else
00452    handle.sa_handler = (void (*)(...))SigUsr1;
00453 #   endif
00454 #else
00455    handle.sa_handler = SigUsr1;
00456 #endif
00457    sigaction(SIGINT,  &ignore, &saveintr);
00458    sigaction(SIGQUIT, &ignore, &savequit);
00459    sigaction(SIGUSR1, &handle, &saveusr1);
00460 
00461    // Create child...
00462 
00463    int childpid;
00464    if ((childpid = fork()) < 0) {
00465       fprintf(stderr, "%s: error forking child\n", argv[0]);
00466       return 1;
00467    } else if (childpid > 0) {
00468       if (!gNoLogo)
00469          WaitLogo();
00470       WaitChild(childpid);
00471    }
00472 
00473    // Continue with child...
00474 
00475    // Restore original signal actions
00476    sigaction(SIGINT,  &saveintr, 0);
00477    sigaction(SIGQUIT, &savequit, 0);
00478    sigaction(SIGUSR1, &saveusr1, 0);
00479 
00480    // Close X display connection
00481    CloseDisplay();
00482 
00483    // Child is going to overlay itself with the actual ROOT module...
00484 
00485    // Build argv vector
00486    argvv = new char* [argc+2];
00487 #ifdef ROOTBINDIR
00488    snprintf(arg0, sizeof(arg0), "%s/%s", ROOTBINDIR, ROOTBINARY);
00489 #else
00490    snprintf(arg0, sizeof(arg0), "%s/bin/%s", getenv("ROOTSYS"), ROOTBINARY);
00491 #endif
00492    argvv[0] = arg0;
00493    argvv[1] = (char *) "-splash";
00494 
00495    for (i = 1; i < argc; i++)
00496       argvv[1+i] = argv[i];
00497    argvv[1+i] = 0;
00498 
00499    // Make sure library path is set
00500    SetLibraryPath();
00501 
00502    // Execute actual ROOT module
00503    execv(arg0, argvv);
00504 
00505    // Exec failed
00506 #ifndef ROOTBINDIR
00507    fprintf(stderr,
00508            "%s: can't start ROOT -- check that %s/bin/%s exists!\n",
00509            argv[0], getenv("ROOTSYS"), ROOTBINARY);
00510 #else
00511    fprintf(stderr, "%s: can't start ROOT -- check that %s/%s exists!\n",
00512            argv[0], ROOTBINDIR, ROOTBINARY);
00513 #endif
00514 
00515    return 1;
00516 }

Generated on Tue Jul 5 15:14:37 2011 for ROOT_528-00b_version by  doxygen 1.5.1