00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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];
00179 char buf[kMAXPATHLEN];
00180 pid_t pid;
00181
00182
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
00220
00221 if (!getenv("DISPLAY")) {
00222 char *tty = ttyname(0);
00223 if (tty) {
00224 tty += 5;
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
00256 }
00257 free(gUtmpContents);
00258 }
00259 }
00260 }
00261
00262 static void SetLibraryPath()
00263 {
00264 #ifndef ROOTLIBDIR
00265
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
00321
00322 if (!gNoLogo)
00323 PopdownLogo();
00324 }
00325
00326 static void WaitChild(int childpid)
00327 {
00328
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)) {
00346 raise(SIGTSTP);
00347 kill(childpid, SIGCONT);
00348 }
00349 } while (WIFSTOPPED(status));
00350
00351 exit(0);
00352 }
00353
00354 static void PrintUsage(char *pname)
00355 {
00356
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
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
00392
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
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
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
00474
00475
00476 sigaction(SIGINT, &saveintr, 0);
00477 sigaction(SIGQUIT, &savequit, 0);
00478 sigaction(SIGUSR1, &saveusr1, 0);
00479
00480
00481 CloseDisplay();
00482
00483
00484
00485
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
00500 SetLibraryPath();
00501
00502
00503 execv(arg0, argvv);
00504
00505
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 }