XrdConfig.cc

Go to the documentation of this file.
00001 /*******************************************************************************/
00002 /*                                                                            */
00003 /*                          X r d C o n f i g . c c                           */
00004 /*                                                                            */
00005 /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*       All Rights Reserved. See XrdInfo.cc for complete License Terms       */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*                DE-AC03-76-SFO0515 with the Deprtment of Energy             */
00009 /******************************************************************************/
00010 
00011 //         $Id: XrdConfig.cc 38011 2011-02-08 18:35:57Z ganis $
00012 
00013 const char *XrdConfigCVSID = "$Id: XrdConfig.cc 38011 2011-02-08 18:35:57Z ganis $";
00014 
00015 /*
00016    The default port number comes from:
00017    1) The command line option,
00018    2) The config file,
00019    3) The /etc/services file for service corresponding to the program name.
00020 */
00021   
00022 #include <unistd.h>
00023 #include <ctype.h>
00024 #include <pwd.h>
00025 #include <string.h>
00026 #include <stdio.h>
00027 #include <sys/param.h>
00028 #include <sys/resource.h>
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031 
00032 #include "Xrd/XrdBuffer.hh"
00033 #include "Xrd/XrdConfig.hh"
00034 #include "Xrd/XrdInet.hh"
00035 #include "Xrd/XrdLink.hh"
00036 #include "Xrd/XrdPoll.hh"
00037 #include "Xrd/XrdProtLoad.hh"
00038 #include "Xrd/XrdScheduler.hh"
00039 #include "Xrd/XrdStats.hh"
00040 #include "Xrd/XrdTrace.hh"
00041 #include "Xrd/XrdInfo.hh"
00042 
00043 #include "XrdNet/XrdNetDNS.hh"
00044 #include "XrdNet/XrdNetSecurity.hh"
00045 
00046 #include "XrdOuc/XrdOuca2x.hh"
00047 #include "XrdOuc/XrdOucEnv.hh"
00048 #include "XrdOuc/XrdOucStream.hh"
00049 #include "XrdOuc/XrdOucUtils.hh"
00050 #include "XrdSys/XrdSysError.hh"
00051 #include "XrdSys/XrdSysHeaders.hh"
00052 #include "XrdSys/XrdSysLogger.hh"
00053 #include "XrdSys/XrdSysTimer.hh"
00054 
00055 #ifdef __linux__
00056 #include <netinet/tcp.h>
00057 #endif
00058 #ifdef __macos__
00059 #include <AvailabilityMacros.h>
00060 #endif
00061 
00062 /******************************************************************************/
00063 /*           G l o b a l   C o n f i g u r a t i o n   O b j e c t            */
00064 /******************************************************************************/
00065 
00066        XrdBuffManager    XrdBuffPool;
00067 
00068        int               XrdNetTCPlep = -1;
00069        XrdInet          *XrdNetTCP[XrdProtLoad::ProtoMax+1] = {0};
00070 extern XrdInet          *XrdNetADM;
00071 
00072 extern XrdScheduler      XrdSched;
00073 
00074 extern XrdSysError       XrdLog;
00075 
00076 extern XrdSysLogger      XrdLogger;
00077 
00078 extern XrdSysThread     *XrdThread;
00079 
00080 extern XrdOucTrace       XrdTrace;
00081 
00082        const char       *XrdConfig::TraceID = "Config";
00083 
00084 /******************************************************************************/
00085 /*                               d e f i n e s                                */
00086 /******************************************************************************/
00087 
00088 #define TS_Xeq(x,m)    if (!strcmp(x,var)) return m(eDest, Config);
00089 
00090 #ifndef S_IAMB
00091 #define S_IAMB  0x1FF
00092 #endif
00093 
00094 /******************************************************************************/
00095 /*                         L o c a l   C l a s s e s                          */
00096 /******************************************************************************/
00097 
00098 class XrdConfigProt
00099 {
00100 public:
00101 
00102 XrdConfigProt  *Next;
00103 char           *proname;
00104 char           *libpath;
00105 char           *parms;
00106 int             port;
00107 int             wanopt;
00108 
00109                 XrdConfigProt(char *pn, char *ln, char *pp, int np=-1, int wo=0)
00110                     {Next = 0; proname = pn; libpath = ln; parms = pp; 
00111                      port=np; wanopt = wo;
00112                     }
00113                ~XrdConfigProt()
00114                     {free(proname);
00115                      if (libpath) free(libpath);
00116                      if (parms)   free(parms);
00117                     }
00118 };
00119 
00120 class XrdLogWorker : XrdJob
00121 {
00122 public:
00123 
00124      void DoIt() {XrdLog.Say(0, XrdBANNER);
00125                   XrdLog.Say(0, mememe, " running.");
00126                   midnite += 86400;
00127                   XrdSched.Schedule((XrdJob *)this, midnite);
00128                  }
00129 
00130           XrdLogWorker(char *who) : XrdJob("midnight runner")
00131                          {midnite = XrdSysTimer::Midnight() + 86400;
00132                           mememe = strdup(who);
00133                           XrdSched.Schedule((XrdJob *)this, midnite);
00134                          }
00135          ~XrdLogWorker() {}
00136 private:
00137 time_t midnite;
00138 const char *mememe;
00139 };
00140 
00141 /******************************************************************************/
00142 /*                           C o n s t r u c t o r                            */
00143 /******************************************************************************/
00144   
00145 XrdConfig::XrdConfig(void)
00146 {
00147 
00148 // Preset all variables with common defaults
00149 //
00150    PortTCP  = -1;
00151    PortUDP  = -1;
00152    PortWAN  = 0;
00153    ConfigFN = 0;
00154    myInsName= 0;
00155    AdminPath= strdup("/tmp");
00156    AdminMode= 0700;
00157    Police   = 0;
00158    Net_Blen = 0;  // Accept OS default (leave Linux autotune in effect)
00159    Net_Opts = 0;
00160    Wan_Blen = 1024*1024; // Default window size 1M
00161    Wan_Opts = 0;
00162    setSched = 1;
00163    repDest[0] = 0;
00164    repDest[1] = 0;
00165    repInt     = 600;
00166    repOpts    = 0;
00167 
00168    Firstcp = Lastcp = 0;
00169 
00170    ProtInfo.eDest   = &XrdLog;          // Stable -> Error Message/Logging Handler
00171    ProtInfo.NetTCP  = 0;                // Stable -> Network Object
00172    ProtInfo.BPool   = &XrdBuffPool;     // Stable -> Buffer Pool Manager
00173    ProtInfo.Sched   = &XrdSched;        // Stable -> System Scheduler
00174    ProtInfo.ConfigFN= 0;                // We will fill this in later
00175    ProtInfo.Stats   = 0;                // We will fill this in later
00176    ProtInfo.Trace   = &XrdTrace;        // Stable -> Trace Information
00177    ProtInfo.Threads = 0;                // Stable -> The thread manager (later)
00178    ProtInfo.AdmPath = AdminPath;        // Stable -> The admin path
00179    ProtInfo.AdmMode = AdminMode;        // Stable -> The admin path mode
00180 
00181    ProtInfo.Format   = XrdFORMATB;
00182    ProtInfo.WANPort  = 0;
00183    ProtInfo.WANWSize = 0;
00184    ProtInfo.WSize    = 0;
00185    ProtInfo.ConnMax  = -1;     // Max       connections (fd limit)
00186    ProtInfo.readWait = 3*1000; // Wait time for data before we reschedule
00187    ProtInfo.idleWait = 0;      // Seconds connection may remain idle (0=off)
00188    ProtInfo.hailWait =30*1000; // Wait time for data before we drop connection
00189    ProtInfo.DebugON  = 0;      // 1 if started with -d
00190    ProtInfo.argc     = 0;
00191    ProtInfo.argv     = 0;
00192 }
00193   
00194 /******************************************************************************/
00195 /*                             C o n f i g u r e                              */
00196 /******************************************************************************/
00197   
00198 int XrdConfig::Configure(int argc, char **argv)
00199 {
00200 /*
00201   Function: Establish configuration at start up time.
00202 
00203   Input:    None.
00204 
00205   Output:   0 upon success or !0 otherwise.
00206 */
00207    const char *xrdInst="XRDINSTANCE=";
00208 
00209    static sockaddr myIPAddr;
00210    int n, retc, dotrim = 1, NoGo = 0, aP = 1, clPort = -1, optbg = 0;
00211    const char *temp;
00212    char c, buff[512], *dfltProt, *logfn = 0;
00213    long long logkeep = 0;
00214    uid_t myUid = 0;
00215    gid_t myGid = 0;
00216    extern char *optarg;
00217    extern int optind, opterr;
00218 
00219 // Obtain the protocol name we will be using
00220 //
00221     retc = strlen(argv[0]);
00222     while(retc--) if (argv[0][retc] == '/') break;
00223     myProg = dfltProt = &argv[0][retc+1];
00224 
00225 // Process the options
00226 //
00227    opterr = 0;
00228    if (argc > 1 && '-' == *argv[1]) 
00229       while ((c = getopt(argc,argv,"bc:dhHk:l:n:p:P:R:"))
00230              && ((unsigned char)c != 0xff))
00231      { switch(c)
00232        {
00233        case 'b': optbg = 1;
00234                  break;
00235        case 'c': if (ConfigFN) free(ConfigFN);
00236                  ConfigFN = strdup(optarg);
00237                  break;
00238        case 'd': XrdTrace.What |= TRACE_ALL;
00239                  ProtInfo.DebugON = 1;
00240                  putenv((char *)"XRDDEBUG=1"); // XrdOucEnv::Export()
00241                  break;
00242        case 'h': Usage(0);
00243                  break;
00244        case 'H': Usage(-1);
00245                  break;
00246        case 'k': n = strlen(optarg)-1;
00247                  retc = (isalpha(optarg[n])
00248                         ? XrdOuca2x::a2sz(XrdLog,"keep size", optarg,&logkeep)
00249                         : XrdOuca2x::a2ll(XrdLog,"keep count",optarg,&logkeep));
00250                  if (retc) Usage(1);
00251                  if (!isalpha(optarg[n])) logkeep = -logkeep;
00252                  break;
00253        case 'l': if (logfn) free(logfn);
00254                  logfn = strdup(optarg);
00255                  break;
00256        case 'n': myInsName = optarg;
00257                  break;
00258        case 'p': if ((clPort = yport(&XrdLog, "tcp", optarg)) < 0) Usage(1);
00259                  break;
00260        case 'P': dfltProt = optarg; dotrim = 0;
00261                  break;
00262        case 'R': if (!(getUG(optarg, myUid, myGid))) Usage(1);
00263                  break;
00264        default:  if (index("clpP", (int)(*(argv[optind-1]+1))))
00265                     {XrdLog.Emsg("Config", argv[optind-1],
00266                                  "parameter not specified.");
00267                      Usage(1);
00268                     }
00269                  argv[aP++] = argv[optind-1];
00270                  if (argv[optind] && *argv[optind] != '-') 
00271                     argv[aP++] = argv[optind++];
00272        }
00273      }
00274 
00275 // Drop into non-privileged state if so requested
00276 //
00277    if (myGid && setegid(myGid))
00278       {XrdLog.Emsg("Config", errno, "set effective gid"); exit(17);}
00279    if (myUid && seteuid(myUid))
00280       {XrdLog.Emsg("Config", errno, "set effective uid"); exit(17);}
00281 
00282 // Pass over any parameters
00283 //
00284    if (aP != optind)
00285       {for ( ; optind < argc; optind++) argv[aP++] = argv[optind];
00286        argv[aP] = 0;
00287        ProtInfo.argc = aP;
00288       } else ProtInfo.argc = argc;
00289    ProtInfo.argv = argv;
00290 
00291 // Resolve background/foreground issues
00292 //
00293    if (optbg) XrdOucUtils::Undercover(XrdLog, !logfn);
00294 
00295 // Bind the log file if we have one
00296 //
00297    if (logfn)
00298       {char *lP;
00299        if (!(logfn = XrdOucUtils::subLogfn(XrdLog, myInsName, logfn))) _exit(16);
00300        if (logkeep) XrdLogger.setKeep(logkeep);
00301        XrdLogger.Bind(logfn, 24*60*60);
00302        if ((lP = rindex(logfn,'/'))) {*(lP+1) = '\0'; lP = logfn;}
00303           else lP = (char *)"./";
00304        XrdOucEnv::Export("XRDLOGDIR", lP);
00305        free(logfn);
00306       }
00307 
00308 // Get the full host name. In theory, we should always get some kind of name.
00309 //
00310    if (!(myName = XrdNetDNS::getHostName()))
00311       {XrdLog.Emsg("Config", "Unable to determine host name; "
00312                              "execution terminated.");
00313        _exit(16);
00314       }
00315 
00316 // Verify that we have a real name. We've had problems with people setting up
00317 // bad /etc/hosts files that can cause connection failures if "allow" is used.
00318 // Otherwise, determine our domain name.
00319 //
00320    if (isdigit(*myName) && (isdigit(*(myName+1)) || *(myName+1) == '.'))
00321       {XrdLog.Emsg("Config", myName, "is not the true host name of this machine.");
00322        XrdLog.Emsg("Config", "Verify that the '/etc/hosts' file is correct and "
00323                              "this machine is registered in DNS.");
00324        XrdLog.Emsg("Config", "Execution continues but connection failures may occur.");
00325        myDomain = 0;
00326       } else if (!(myDomain = index(myName, '.')))
00327                 XrdLog.Say("Config warning: this hostname, ", myName,
00328                             ", is registered without a domain qualification.");
00329 
00330 // Get our IP address
00331 //
00332    XrdNetDNS::getHostAddr(myName, &myIPAddr);
00333    ProtInfo.myName = myName;
00334    ProtInfo.myAddr = &myIPAddr;
00335    ProtInfo.myInst = XrdOucUtils::InstName(myInsName);
00336    ProtInfo.myProg = myProg;
00337 
00338 // Set the Environmental variable to hold the instance name
00339 // XRDINSTANCE=<pgm> <instance name>@<host name>
00340 //                 XrdOucEnv::Export("XRDINSTANCE")
00341 //
00342    sprintf(buff,"%s%s %s@%s", xrdInst, myProg, ProtInfo.myInst, myName);
00343    myInstance = strdup(buff);
00344    putenv(myInstance);   // XrdOucEnv::Export("XRDINSTANCE",...)
00345    myInstance += strlen(xrdInst);
00346    XrdOucEnv::Export("XRDHOST", myName);
00347    XrdOucEnv::Export("XRDNAME", ProtInfo.myInst);
00348    XrdOucEnv::Export("XRDPROG", myProg);
00349 
00350 // Put out the herald
00351 //
00352    XrdLog.Say(0, "Scalla is starting. . .");
00353    XrdLog.Say(XrdBANNER);
00354 
00355 // Setup the initial required protocol
00356 //
00357    if (dotrim && *dfltProt != '.' )
00358       {char *p = dfltProt;
00359        while (*p && *p != '.') p++;
00360        if (*p == '.') *p = '\0';
00361       }
00362    Firstcp = Lastcp = new XrdConfigProt(strdup(dfltProt), 0, 0);
00363 
00364 // Process the configuration file, if one is present
00365 //
00366    XrdLog.Say("++++++ ", myInstance, " initialization started.");
00367    if (ConfigFN && *ConfigFN)
00368       {XrdLog.Say("Config using configuration file ", ConfigFN);
00369        ProtInfo.ConfigFN = ConfigFN;
00370        XrdOucEnv::Export("XRDCONFIGFN", ConfigFN);
00371        NoGo = ConfigProc();
00372       }
00373    if (clPort >= 0) PortTCP = clPort;
00374    if (ProtInfo.DebugON) 
00375       {XrdTrace.What = TRACE_ALL;
00376        XrdSysThread::setDebug(&XrdLog);
00377       }
00378    if (!NoGo) NoGo = Setup(dfltProt);
00379    ProtInfo.Threads = XrdThread;
00380 
00381 // If we hae a net name change the working directory
00382 //
00383    if (myInsName) XrdOucUtils::makeHome(XrdLog, myInsName);
00384 
00385 // All done, close the stream and return the return code.
00386 //
00387    temp = (NoGo ? " initialization failed." : " initialization completed.");
00388    sprintf(buff, "%s:%d", myInstance, PortTCP);
00389    XrdLog.Say("------ ", buff, temp);
00390    if (logfn) new XrdLogWorker(buff);
00391    return NoGo;
00392 }
00393 
00394 /******************************************************************************/
00395 /*                             C o n f i g X e q                              */
00396 /******************************************************************************/
00397 
00398 int XrdConfig::ConfigXeq(char *var, XrdOucStream &Config, XrdSysError *eDest)
00399 {
00400    int dynamic;
00401 
00402    // Determine whether is is dynamic or not
00403    //
00404    if (eDest) dynamic = 1;
00405       else   {dynamic = 0; eDest = &XrdLog;}
00406 
00407    // Process common items
00408    //
00409    TS_Xeq("buffers",       xbuf);
00410    TS_Xeq("network",       xnet);
00411    TS_Xeq("sched",         xsched);
00412    TS_Xeq("trace",         xtrace);
00413 
00414    // Process items that can only be processed once
00415    //
00416    if (!dynamic)
00417    {
00418    TS_Xeq("adminpath",     xapath);
00419    TS_Xeq("allow",         xallow);
00420    TS_Xeq("port",          xport);
00421    TS_Xeq("protocol",      xprot);
00422    TS_Xeq("report",        xrep);
00423    TS_Xeq("timeout",       xtmo);
00424    }
00425 
00426    // No match found, complain.
00427    //
00428    eDest->Say("Config warning: ignoring unknown xrd directive '",var,"'.");
00429    Config.Echo();
00430    return 0;
00431 }
00432 
00433 /******************************************************************************/
00434 /*                     P r i v a t e   F u n c t i o n s                      */
00435 /******************************************************************************/
00436 /******************************************************************************/
00437 /*                               A S o c k e t                                */
00438 /******************************************************************************/
00439   
00440 int XrdConfig::ASocket(const char *path, const char *fname, mode_t mode)
00441 {
00442    char xpath[MAXPATHLEN+8], sokpath[108];
00443    int  plen = strlen(path), flen = strlen(fname);
00444    int rc;
00445 
00446 // Make sure we can fit everything in our buffer
00447 //
00448    if ((plen + flen + 3) > (int)sizeof(sokpath))
00449       {XrdLog.Emsg("Config", "admin path", path, "too long");
00450        return 1;
00451       }
00452 
00453 // Create the directory path
00454 //
00455    strcpy(xpath, path);
00456    if ((rc = XrdOucUtils::makePath(xpath, mode)))
00457        {XrdLog.Emsg("Config", rc, "create admin path", xpath);
00458         return 1;
00459        }
00460 
00461 // *!*!* At this point we do not yet support the admin path for xrd.
00462 // sp we comment out all of the following code.
00463 
00464 /*
00465 // Construct the actual socket name
00466 //
00467   if (sokpath[plen-1] != '/') sokpath[plen++] = '/';
00468   strcpy(&sokpath[plen], fname);
00469 
00470 // Create an admin network
00471 //
00472    XrdNetADM = new XrdInet(&XrdLog);
00473    if (myDomain) XrdNetADM->setDomain(myDomain);
00474 
00475 // Bind the netwok to the named socket
00476 //
00477    if (!XrdNetADM->Bind(sokpath)) return 1;
00478 
00479 // Set the mode and return
00480 //
00481    chmod(sokpath, mode); // This may fail on some platforms
00482 */
00483    return 0;
00484 }
00485 
00486 /******************************************************************************/
00487 /*                            C o n f i g P r o c                             */
00488 /******************************************************************************/
00489   
00490 int XrdConfig::ConfigProc()
00491 {
00492   char *var;
00493   int  cfgFD, retc, NoGo = 0;
00494   XrdOucEnv myEnv;
00495   XrdOucStream Config(&XrdLog, myInstance, &myEnv, "=====> ");
00496 
00497 // Try to open the configuration file.
00498 //
00499    if ( (cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
00500       {XrdLog.Emsg("Config", errno, "open config file", ConfigFN);
00501        return 1;
00502       }
00503    Config.Attach(cfgFD);
00504 
00505 // Now start reading records until eof.
00506 //
00507    while((var = Config.GetMyFirstWord()))
00508         if (!strncmp(var, "xrd.", 4)
00509         ||  !strcmp (var, "all.adminpath"))
00510            if (ConfigXeq(var+4, Config)) {Config.Echo(); NoGo = 1;}
00511 
00512 // Now check if any errors occured during file i/o
00513 //
00514    if ((retc = Config.LastError()))
00515       NoGo = XrdLog.Emsg("Config", retc, "read config file", ConfigFN);
00516    Config.Close();
00517 
00518 // Return final return code
00519 //
00520    return NoGo;
00521 }
00522 
00523 /******************************************************************************/
00524 /*                                 g e t U G                                  */
00525 /******************************************************************************/
00526   
00527 int XrdConfig::getUG(char *parm, uid_t &newUid, gid_t &newGid)
00528 {
00529    struct passwd *pp;
00530 
00531 // Get the userid entry
00532 //
00533    if (!(*parm))
00534       {XrdLog.Emsg("Config", "-R user not specified."); return 0;}
00535 
00536    if (isdigit(*parm))
00537       {if (!(newUid = atol(parm)))
00538           {XrdLog.Emsg("Config", "-R", parm, "is invalid"); return 0;}
00539        pp = getpwuid(newUid);
00540       }
00541       else pp = getpwnam(parm);
00542 
00543 // Make sure it is valid and acceptable
00544 //
00545    if (!pp) 
00546       {XrdLog.Emsg("Config", errno, "retrieve -R user password entry");
00547        return 0;
00548       }
00549    if (!(newUid = pp->pw_uid))
00550       {XrdLog.Emsg("Config", "-R", parm, "is still unacceptably a superuser!");
00551        return 0;
00552       }
00553    newGid = pp->pw_gid;
00554    return 1;
00555 }
00556 
00557 /******************************************************************************/
00558 /*                                s e t F D L                                 */
00559 /******************************************************************************/
00560   
00561 int XrdConfig::setFDL()
00562 {
00563    struct rlimit rlim;
00564    char buff[100];
00565 
00566 // Get the resource limit
00567 //
00568    if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
00569       return XrdLog.Emsg("Config", errno, "get FD limit");
00570 
00571 // Set the limit to the maximum allowed
00572 //
00573    rlim.rlim_cur = rlim.rlim_max;
00574 #if (defined(__macos__) && defined(MAC_OS_X_VERSION_10_5))
00575    if (rlim.rlim_cur == RLIM_INFINITY || rlim.rlim_cur > OPEN_MAX)
00576      rlim.rlim_cur = OPEN_MAX;
00577 #endif
00578    if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
00579       return XrdLog.Emsg("Config", errno,"set FD limit");
00580 
00581 // Obtain the actual limit now
00582 //
00583    if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
00584       return XrdLog.Emsg("Config", errno, "get FD limit");
00585 
00586 // Establish operating limit
00587 //
00588    ProtInfo.ConnMax = rlim.rlim_cur;
00589    sprintf(buff, "%d", ProtInfo.ConnMax);
00590    XrdLog.Say("Config maximum number of connections restricted to ", buff);
00591 
00592    return 0;
00593 }
00594 
00595 /******************************************************************************/
00596 /*                                 S e t u p                                  */
00597 /******************************************************************************/
00598   
00599 int XrdConfig::Setup(char *dfltp)
00600 {
00601    XrdInet *NetWAN;
00602    XrdConfigProt *cp, *pp, *po, *POrder = 0;
00603    int wsz, lastPort = -17;
00604 
00605 // Establish the FD limit
00606 //
00607    if (setFDL()) return 1;
00608 
00609 // Special handling for Linux sendfile()
00610 //
00611 #if defined(__linux__) && defined(TCP_CORK)
00612 {  int sokFD, setON = 1;
00613    if ((sokFD = socket(PF_INET, SOCK_STREAM, 0)) >= 0)
00614       {setsockopt(sokFD, XrdNetDNS::getProtoID("tcp"), TCP_NODELAY,
00615                   &setON, sizeof(setON));
00616        if (setsockopt(sokFD, SOL_TCP, TCP_CORK, &setON, sizeof(setON)) < 0)
00617           XrdLink::sfOK = 0;
00618        close(sokFD);
00619       }
00620 }
00621 #endif
00622 
00623 // Indicate how sendfile is being handled
00624 //
00625    TRACE(NET,"sendfile " <<(XrdLink::sfOK ? "enabled." : "disabled!"));
00626 
00627 // Initialize the buffer manager
00628 //
00629    XrdBuffPool.Init();
00630 
00631 // Start the scheduler
00632 //
00633    XrdSched.Start();
00634 
00635 // Setup the link and socket polling infrastructure
00636 //
00637    if (!XrdLink::Setup(ProtInfo.ConnMax, ProtInfo.idleWait)
00638    ||  !XrdPoll::Setup(ProtInfo.ConnMax)) return 1;
00639 
00640 // Modify the AdminPath to account for any instance name. Note that there is
00641 // a negligible memory leak under ceratin path combinations. Not enough to
00642 // warrant a lot of logic to get around.
00643 //
00644    if (myInsName) ProtInfo.AdmPath = XrdOucUtils::genPath(AdminPath,myInsName);
00645       else ProtInfo.AdmPath = AdminPath;
00646    XrdOucEnv::Export("XRDADMINPATH", ProtInfo.AdmPath);
00647    AdminPath = XrdOucUtils::genPath(AdminPath, myInsName, ".xrd");
00648 
00649 // Setup admin connection now
00650 //
00651    if (ASocket(AdminPath, "admin", (mode_t)AdminMode)) return 1;
00652 
00653 // Determine the default port number (only for xrootd) if not specified.
00654 //
00655    if (PortTCP < 0)  
00656       {if ((PortTCP = XrdNetDNS::getPort(dfltp, "tcp"))) PortUDP = PortTCP;
00657           else PortTCP = -1;
00658       }
00659 
00660 // We now go through all of the protocols and get each respective port
00661 // number and arrange them in descending port number order.
00662 // XrdOucEnv::Export(XRDPORT
00663 //
00664    while((cp = Firstcp))
00665         {ProtInfo.Port = (cp->port < 0 ? PortTCP : cp->port);
00666          XrdOucEnv::Export("XRDPORT", ProtInfo.Port);
00667          if ((cp->port = XrdProtLoad::Port(cp->libpath, cp->proname,
00668                                            cp->parms, &ProtInfo)) < 0) return 1;
00669          pp = 0; po = POrder; Firstcp = cp->Next;
00670          while(po && po->port > cp->port) {pp = po; po = po->Next;}
00671          if (pp) {pp->Next = cp;   cp->Next = po;}
00672             else {cp->Next = POrder; POrder = cp;}
00673         }
00674 
00675 // Allocate the statistics object. This is akward since we only know part
00676 // of the current configuration. The object will figure this out later.
00677 //
00678    ProtInfo.Stats = new XrdStats(ProtInfo.myName, POrder->port,
00679                                  ProtInfo.myInst, ProtInfo.myProg);
00680 
00681 // Allocate a WAN port number of we need to
00682 //
00683    if (PortWAN &&  (NetWAN = new XrdInet(&XrdLog, Police)))
00684       {if (Wan_Opts || Wan_Blen) NetWAN->setDefaults(Wan_Opts, Wan_Blen);
00685        if (myDomain) NetWAN->setDomain(myDomain);
00686        if (NetWAN->Bind((PortWAN > 0 ? PortWAN : 0), "tcp")) return 1;
00687        PortWAN  = NetWAN->Port();
00688        wsz      = NetWAN->WSize();
00689        Wan_Blen = (wsz < Wan_Blen || !Wan_Blen ? wsz : Wan_Blen);
00690        TRACE(NET,"WAN port " <<PortWAN <<" wsz=" <<Wan_Blen <<" (" <<wsz <<')');
00691        XrdNetTCP[XrdProtLoad::ProtoMax] = NetWAN;
00692       } else {PortWAN = 0; Wan_Blen = 0;}
00693 
00694 // Load the protocols. For each new protocol port number, create a new
00695 // network object to handle the port dependent communications part. All
00696 // port issues will have been resolved at this point.
00697 //
00698    while((cp= POrder))
00699         {if (cp->port != lastPort)
00700             {XrdNetTCP[++XrdNetTCPlep] = new XrdInet(&XrdLog, Police);
00701              if (Net_Opts || Net_Blen)
00702                 XrdNetTCP[XrdNetTCPlep]->setDefaults(Net_Opts, Net_Blen);
00703              if (myDomain) XrdNetTCP[XrdNetTCPlep]->setDomain(myDomain);
00704              if (XrdNetTCP[XrdNetTCPlep]->Bind(cp->port, "tcp")) return 1;
00705              ProtInfo.Port   = XrdNetTCP[XrdNetTCPlep]->Port();
00706              ProtInfo.NetTCP = XrdNetTCP[XrdNetTCPlep];
00707              wsz             = XrdNetTCP[XrdNetTCPlep]->WSize();
00708              ProtInfo.WSize  = (wsz < Net_Blen || !Net_Blen ? wsz : Net_Blen);
00709              TRACE(NET,"LCL port " <<ProtInfo.Port <<" wsz=" <<ProtInfo.WSize
00710                        <<" (" <<wsz <<')');
00711              if (cp->wanopt)
00712                 {ProtInfo.WANPort = PortWAN;
00713                  ProtInfo.WANWSize= Wan_Blen;
00714                 } else ProtInfo.WANPort = ProtInfo.WANWSize = 0;
00715              XrdOucEnv::Export("XRDPORT", ProtInfo.Port);
00716              lastPort = cp->port;
00717             }
00718          if (!XrdProtLoad::Load(cp->libpath,cp->proname,cp->parms,&ProtInfo))
00719             return 1;
00720          POrder = cp->Next;
00721          delete cp;
00722         }
00723 
00724 // Leave the env port number to be the first used port number. This may
00725 // or may not be the same as the default port number.
00726 //
00727    ProtInfo.Port = XrdNetTCP[0]->Port();
00728    PortTCP = ProtInfo.Port;
00729    XrdOucEnv::Export("XRDPORT", PortTCP);
00730 
00731 // Now check if we have to setup automatic reporting
00732 //
00733    if (repDest[0] != 0 && repOpts) 
00734       ProtInfo.Stats->Report(repDest, repInt, repOpts);
00735 
00736 // All done
00737 //
00738    return 0;
00739 }
00740 
00741 /******************************************************************************/
00742 /*                                 U s a g e                                  */
00743 /******************************************************************************/
00744   
00745 void XrdConfig::Usage(int rc)
00746 {
00747   extern const char *XrdLicense;
00748 
00749   if (rc < 0) cerr <<XrdLicense;
00750      else
00751      cerr <<"\nUsage: " <<myProg <<" [-b] [-c <cfn>] [-d] [-k {n|sz}] [-l <fn>] "
00752             "[-L] [-n name] [-p <port>] [-P <prot>] [<prot_options>]" <<endl;
00753      _exit(rc > 0 ? rc : 0);
00754 }
00755 
00756 /******************************************************************************/
00757 /*                                x a p a t h                                 */
00758 /******************************************************************************/
00759 
00760 /* Function: xapath
00761 
00762    Purpose:  To parse the directive: adminpath <path> [group]
00763 
00764              <path>    the path of the FIFO to use for admin requests.
00765 
00766              group     allows group access to the admin path
00767 
00768    Note: A named socket is created <path>/<name>/.xrd/admin
00769 
00770    Output: 0 upon success or !0 upon failure.
00771 */
00772 
00773 int XrdConfig::xapath(XrdSysError *eDest, XrdOucStream &Config)
00774 {
00775     char *pval, *val;
00776     mode_t mode = S_IRWXU;
00777 
00778 // Get the path
00779 //
00780    pval = Config.GetWord();
00781    if (!pval || !pval[0])
00782       {eDest->Emsg("Config", "adminpath not specified"); return 1;}
00783 
00784 // Make sure it's an absolute path
00785 //
00786    if (*pval != '/')
00787       {eDest->Emsg("Config", "adminpath not absolute"); return 1;}
00788 
00789 // Record the path
00790 //
00791    if (AdminPath) free(AdminPath);
00792    AdminPath = strdup(pval);
00793 
00794 // Get the optional access rights
00795 //
00796    if ((val = Config.GetWord()) && val[0])
00797       {if (!strcmp("group", val)) mode |= S_IRWXG;
00798           else {eDest->Emsg("Config", "invalid admin path modifier -", val);
00799                 return 1;
00800                }
00801       }
00802    AdminMode = ProtInfo.AdmMode = mode;
00803    return 0;
00804 }
00805   
00806 /******************************************************************************/
00807 /*                                x a l l o w                                 */
00808 /******************************************************************************/
00809 
00810 /* Function: xallow
00811 
00812    Purpose:  To parse the directive: allow {host | netgroup} <name>
00813 
00814              <name> The dns name of the host that is allowed to connect or the
00815                     netgroup name the host must be a member of. For DNS names,
00816                     a single asterisk may be specified anywhere in the name.
00817 
00818    Output: 0 upon success or !0 upon failure.
00819 */
00820 
00821 int XrdConfig::xallow(XrdSysError *eDest, XrdOucStream &Config)
00822 {
00823     char *val;
00824     int ishost;
00825 
00826     if (!(val = Config.GetWord()))
00827        {eDest->Emsg("Config", "allow type not specified"); return 1;}
00828 
00829     if (!strcmp(val, "host")) ishost = 1;
00830        else if (!strcmp(val, "netgroup")) ishost = 0;
00831                else {eDest->Emsg("Config", "invalid allow type -", val);
00832                      return 1;
00833                     }
00834 
00835     if (!(val = Config.GetWord()))
00836        {eDest->Emsg("Config", "allow target name not specified"); return 1;}
00837 
00838     if (!Police) Police = new XrdNetSecurity();
00839     if (ishost)  Police->AddHost(val);
00840        else      Police->AddNetGroup(val);
00841 
00842     return 0;
00843 }
00844 
00845 /******************************************************************************/
00846 /*                                  x b u f                                   */
00847 /******************************************************************************/
00848 
00849 /* Function: xbuf
00850 
00851    Purpose:  To parse the directive: buffers <memsz> [<rint>]
00852 
00853              <memsz>    maximum amount of memory devoted to buffers
00854              <rint>     minimum buffer reshape interval in seconds
00855 
00856    Output: 0 upon success or !0 upon failure.
00857 */
00858 int XrdConfig::xbuf(XrdSysError *eDest, XrdOucStream &Config)
00859 {
00860     int bint = -1;
00861     long long blim;
00862     char *val;
00863 
00864     if (!(val = Config.GetWord()))
00865        {eDest->Emsg("Config", "buffer memory limit not specified"); return 1;}
00866     if (XrdOuca2x::a2sz(*eDest,"buffer limit value",val,&blim,
00867                        (long long)1024*1024)) return 1;
00868 
00869     if ((val = Config.GetWord()))
00870        if (XrdOuca2x::a2tm(*eDest,"reshape interval", val, &bint, 300))
00871           return 1;
00872 
00873     XrdBuffPool.Set((int)blim, bint);
00874     return 0;
00875 }
00876 
00877 /******************************************************************************/
00878 /*                                  x n e t                                   */
00879 /******************************************************************************/
00880 
00881 /* Function: xnet
00882 
00883    Purpose:  To parse directive: network [wan] [keepalive] [buffsz <blen>]
00884                                          [[no]dnr]
00885 
00886              wan       parameters apply only to the wan port
00887              keepalive sets the socket keepalive option.
00888              <blen>    is the socket's send/rcv buffer size.
00889              [no]dnr   do [not] perform a reverse DNS lookup if not needed.
00890 
00891    Output: 0 upon success or !0 upon failure.
00892 */
00893 
00894 int XrdConfig::xnet(XrdSysError *eDest, XrdOucStream &Config)
00895 {
00896     char *val;
00897     int  i, V_keep = 0, V_nodnr = 0, V_iswan = 0, V_blen = -1;
00898     long long llp;
00899     static struct netopts {const char *opname; int hasarg; int opval;
00900                            int  *oploc;  const char *etxt;}
00901            ntopts[] =
00902        {
00903         {"keepalive",  0, 1, &V_keep,   "option"},
00904         {"buffsz",     1, 0, &V_blen,   "network buffsz"},
00905         {"dnr",        0, 0, &V_nodnr,  "option"},
00906         {"nodnr",      0, 1, &V_nodnr,  "option"},
00907         {"wan",        0, 1, &V_iswan,  "option"}
00908        };
00909     int numopts = sizeof(ntopts)/sizeof(struct netopts);
00910 
00911     if (!(val = Config.GetWord()))
00912        {eDest->Emsg("Config", "net option not specified"); return 1;}
00913 
00914     while (val)
00915     {for (i = 0; i < numopts; i++)
00916          if (!strcmp(val, ntopts[i].opname))
00917             {if (!ntopts[i].hasarg) llp=static_cast<long long>(ntopts[i].opval);
00918                 else {if (!(val = Config.GetWord()))
00919                          {eDest->Emsg("Config", "network",
00920                               ntopts[i].opname, ntopts[i].etxt);
00921                           return 1;
00922                          }
00923                       if (XrdOuca2x::a2sz(*eDest,ntopts[i].etxt,val,&llp,0))
00924                          return 1;
00925                      }
00926              *ntopts[i].oploc = (int)llp;
00927               break;
00928             }
00929       if (i >= numopts)
00930          eDest->Say("Config warning: ignoring invalid net option '",val,"'.");
00931       val = Config.GetWord();
00932      }
00933 
00934      if (V_iswan)
00935         {if (V_blen >= 0) Wan_Blen = V_blen;
00936          Wan_Opts  = (V_keep  ? XRDNET_KEEPALIVE : 0)
00937                    | (V_nodnr ? XRDNET_NORLKUP   : 0);
00938          if (!PortWAN) PortWAN = -1;
00939         } else {
00940          if (V_blen >= 0) Net_Blen = V_blen;
00941          Net_Opts  = (V_keep  ? XRDNET_KEEPALIVE : 0)
00942                    | (V_nodnr ? XRDNET_NORLKUP   : 0);
00943         }
00944      return 0;
00945 }
00946 
00947 /******************************************************************************/
00948 /*                                 x p o r t                                  */
00949 /******************************************************************************/
00950 
00951 /* Function: xport
00952 
00953    Purpose:  To parse the directive: port [wan] <tcpnum>
00954                                                [if [<hlst>] [named <nlst>]]
00955 
00956              wan        apply this to the wan port
00957              <tcpnum>   number of the tcp port for incomming requests
00958              <hlst>     list of applicable host patterns
00959              <nlst>     list of applicable instance names.
00960 
00961    Output: 0 upon success or !0 upon failure.
00962 */
00963 int XrdConfig::xport(XrdSysError *eDest, XrdOucStream &Config)
00964 {   int rc, iswan = 0, pnum = 0;
00965     char *val, cport[32];
00966 
00967     do {if (!(val = Config.GetWord()))
00968            {eDest->Emsg("Config", "tcp port not specified"); return 1;}
00969         if (strcmp("wan", val) || iswan) break;
00970         iswan = 1;
00971        } while(1);
00972 
00973     strncpy(cport, val, sizeof(cport)-1); cport[sizeof(cport)-1] = '\0';
00974 
00975     if ((val = Config.GetWord()) && !strcmp("if", val))
00976        if ((rc = XrdOucUtils::doIf(eDest,Config, "port directive", myName,
00977                               ProtInfo.myInst, myProg)) <= 0) return (rc < 0);
00978 
00979     if ((pnum = yport(eDest, "tcp", cport)) < 0) return 1;
00980     if (iswan) PortWAN = pnum;
00981        else PortTCP = PortUDP = pnum;
00982 
00983     return 0;
00984 }
00985 
00986 /******************************************************************************/
00987 
00988 int XrdConfig::yport(XrdSysError *eDest, const char *ptype, const char *val)
00989 {
00990     int pnum;
00991     if (!strcmp("any", val)) return 0;
00992 
00993     const char *invp = (*ptype == 't' ? "tcp port" : "udp port" );
00994     const char *invs = (*ptype == 't' ? "Unable to find tcp service" :
00995                                         "Unable to find udp service" );
00996 
00997     if (isdigit(*val))
00998        {if (XrdOuca2x::a2i(*eDest,invp,val,&pnum,1,65535)) return 0;}
00999        else if (!(pnum = XrdNetDNS::getPort(val, "tcp")))
01000                {eDest->Emsg("Config", invs, val);
01001                 return -1;
01002                }
01003     return pnum;
01004 }
01005   
01006 /******************************************************************************/
01007 /*                                 x p r o t                                  */
01008 /******************************************************************************/
01009 
01010 /* Function: xprot
01011 
01012    Purpose:  To parse the directive: protocol [wan] <name>[:<port>] <loc> [<parm>]
01013 
01014              wan    The protocol is WAN optimized
01015              <name> The name of the protocol (e.g., rootd)
01016              <port> Port binding for the protocol, if not the default.
01017              <loc>  The shared library in which it is located.
01018              <parm> A one line parameter to be passed to the protocol.
01019 
01020    Output: 0 upon success or !0 upon failure.
01021 */
01022 
01023 int XrdConfig::xprot(XrdSysError *eDest, XrdOucStream &Config)
01024 {
01025     XrdConfigProt *cpp;
01026     char *val, *parms, *lib, proname[64], buff[1024];
01027     int vlen, bleft = sizeof(buff), portnum = -1, wanopt = 0;
01028 
01029     do {if (!(val = Config.GetWord()))
01030            {eDest->Emsg("Config", "protocol name not specified"); return 1;}
01031         if (wanopt || strcmp("wan", val)) break;
01032         wanopt = 1;
01033        } while(1);
01034 
01035     if (strlen(val) > sizeof(proname)-1)
01036        {eDest->Emsg("Config", "protocol name is too long"); return 1;}
01037     strcpy(proname, val);
01038 
01039     if (!(val = Config.GetWord()))
01040        {eDest->Emsg("Config", "protocol library not specified"); return 1;}
01041     if (strcmp("*", val)) lib = strdup(val);
01042        else lib = 0;
01043 
01044     parms = buff;
01045     while((val = Config.GetWord()))
01046          {vlen = strlen(val); bleft -= (vlen+1);
01047           if (bleft <= 0)
01048              {eDest->Emsg("Config", "Too many parms for protocol", proname);
01049               return 1;
01050              }
01051           *parms = ' '; parms++; strcpy(parms, val); parms += vlen;
01052          }
01053     if (parms != buff) parms = strdup(buff+1);
01054        else parms = 0;
01055 
01056     if ((val = index(proname, ':')))
01057        {if ((portnum = yport(&XrdLog, "tcp", val+1)) < 0) return 1;
01058            else *val = '\0';
01059        }
01060 
01061     if (wanopt && !PortWAN) PortWAN = 1;
01062 
01063     if ((cpp = Firstcp))
01064        do {if (!strcmp(proname, cpp->proname))
01065               {if (cpp->libpath) free(cpp->libpath);
01066                if (cpp->parms)   free(cpp->parms);
01067                cpp->libpath = lib;
01068                cpp->parms   = parms;
01069                cpp->wanopt  = wanopt;
01070                return 0;
01071               }
01072           } while((cpp = cpp->Next));
01073 
01074     if (lib)
01075        {cpp = new XrdConfigProt(strdup(proname), lib, parms, portnum, wanopt);
01076         if (Lastcp) Lastcp->Next = cpp;
01077            else    Firstcp = cpp;
01078         Lastcp = cpp;
01079        }
01080 
01081     return 0;
01082 }
01083 
01084 /******************************************************************************/
01085 /*                                  x r e p                                   */
01086 /******************************************************************************/
01087   
01088 /* Function: xrep
01089 
01090    Purpose:  To parse the directive: report <dest1>[,<dest2>]
01091                                             [every <sec>] <opts>
01092 
01093              <dest1>   where a UDP based report is to be sent. It may be a
01094                        <host:port> or a local named UDP pipe (i.e., "/...").
01095 
01096              <dest2>   A secondary destination.
01097 
01098              <sec>     the reporting interval. The default is 10 minutes.
01099 
01100              <opts>    What to report. "all" is the default.
01101 
01102   Output: 0 upon success or !0 upon failure.
01103 */
01104 
01105 int XrdConfig::xrep(XrdSysError *eDest, XrdOucStream &Config)
01106 {
01107    static struct repopts {const char *opname; int opval;} rpopts[] =
01108        {
01109         {"all",      XRD_STATS_ALL},
01110         {"buff",     XRD_STATS_BUFF},
01111         {"info",     XRD_STATS_INFO},
01112         {"link",     XRD_STATS_LINK},
01113         {"poll",     XRD_STATS_POLL},
01114         {"process",  XRD_STATS_PROC},
01115         {"protocols",XRD_STATS_PROT},
01116         {"prot",     XRD_STATS_PROT},
01117         {"sched",    XRD_STATS_SCHD},
01118         {"sgen",     XRD_STATS_SGEN},
01119         {"sync",     XRD_STATS_SYNC},
01120         {"syncwp",   XRD_STATS_SYNCA}
01121        };
01122    int i, neg, numopts = sizeof(rpopts)/sizeof(struct repopts);
01123    char  *val, *cp;
01124 
01125    if (!(val = Config.GetWord()))
01126       {eDest->Emsg("Config", "report parameters not specified"); return 1;}
01127 
01128 // Cleanup to start anew
01129 //
01130    if (repDest[0]) {free(repDest[0]); repDest[0] = 0;}
01131    if (repDest[1]) {free(repDest[1]); repDest[1] = 0;}
01132    repOpts = 0;
01133    repInt  = 600;
01134 
01135 // Decode the destination
01136 //
01137    if ((cp = (char *)index(val, ',')))
01138       {if (!*(cp+1))
01139           {eDest->Emsg("Config","malformed report destination -",val); return 1;}
01140           else { repDest[1] = cp+1; *cp = '\0';}
01141       }
01142    repDest[0] = val;
01143    for (i = 0; i < 2; i++)
01144        {if (!(val = repDest[i])) break;
01145         if (*val != '/' && (!(cp = index(val, (int)':')) || !atoi(cp+1)))
01146            {eDest->Emsg("Config","report dest port missing or invalid in",val);
01147             return 1;
01148            }
01149         repDest[i] = strdup(val);
01150        }
01151 
01152 // Make sure dests differ
01153 //
01154    if (repDest[0] && repDest[1] && !strcmp(repDest[0], repDest[1]))
01155       {eDest->Emsg("Config", "Warning, report dests are identical.");
01156        free(repDest[1]); repDest[1] = 0;
01157       }
01158 
01159 // Get optional "every"
01160 //
01161    if (!(val = Config.GetWord())) {repOpts = XRD_STATS_ALL; return 0;}
01162    if (!strcmp("every", val))
01163       {if (!(val = Config.GetWord()))
01164           {eDest->Emsg("Config", "report every value not specified"); return 1;}
01165        if (XrdOuca2x::a2tm(*eDest,"report every",val,&repInt,1)) return 1;
01166        val = Config.GetWord();
01167       }
01168 
01169 // Get reporting options
01170 //
01171    while(val)
01172         {if (!strcmp(val, "off")) repOpts = 0;
01173             else {if ((neg = (val[0] == '-' && val[1]))) val++;
01174                   for (i = 0; i < numopts; i++)
01175                       {if (!strcmp(val, rpopts[i].opname))
01176                           {if (neg) repOpts &= ~rpopts[i].opval;
01177                               else  repOpts |=  rpopts[i].opval;
01178                            break;
01179                           }
01180                       }
01181                   if (i >= numopts)
01182                      eDest->Say("Config warning: ignoring invalid report option '",val,"'.");
01183                  }
01184          val = Config.GetWord();
01185         }
01186 
01187 // All done
01188 //
01189    if (!(repOpts & XRD_STATS_ALL)) repOpts = XRD_STATS_ALL & ~XRD_STATS_INFO;
01190    return 0;
01191 }
01192 
01193 /******************************************************************************/
01194 /*                                x s c h e d                                 */
01195 /******************************************************************************/
01196 
01197 /* Function: xsched
01198 
01199    Purpose:  To parse directive: sched [mint <mint>] [maxt <maxt>] [avlt <at>]
01200                                        [idle <idle>] [stksz <qnt>]
01201 
01202              <mint>   is the minimum number of threads that we need. Once
01203                       this number of threads is created, it does not decrease.
01204              <maxt>   maximum number of threads that may be created. The
01205                       actual number of threads will vary between <mint> and
01206                       <maxt>.
01207              <avlt>   Are the number of threads that must be available for
01208                       immediate dispatch. These threads are never bound to a
01209                       connection (i.e., made stickied). Any available threads
01210                       above <ft> will be allowed to stick to a connection.
01211              <idle>   The time (in time spec) between checks for underused
01212                       threads. Those found will be terminated. Default is 780.
01213              <qnt>    The thread stack size in bytes or K, M, or G.
01214 
01215    Output: 0 upon success or 1 upon failure.
01216 */
01217 
01218 int XrdConfig::xsched(XrdSysError *eDest, XrdOucStream &Config)
01219 {
01220     char *val;
01221     long long lpp;
01222     int  i, ppp;
01223     int  V_mint = -1, V_maxt = -1, V_idle = -1, V_avlt = -1;
01224     static struct schedopts {const char *opname; int minv; int *oploc;
01225                              const char *opmsg;} scopts[] =
01226        {
01227         {"stksz",      0,       0, "sched stksz"},
01228         {"mint",       1, &V_mint, "sched mint"},
01229         {"maxt",       1, &V_maxt, "sched maxt"},
01230         {"avlt",       1, &V_avlt, "sched avlt"},
01231         {"idle",       0, &V_idle, "sched idle"}
01232        };
01233     int numopts = sizeof(scopts)/sizeof(struct schedopts);
01234 
01235     if (!(val = Config.GetWord()))
01236        {eDest->Emsg("Config", "sched option not specified"); return 1;}
01237 
01238     while (val)
01239           {for (i = 0; i < numopts; i++)
01240                if (!strcmp(val, scopts[i].opname))
01241                   {if (!(val = Config.GetWord()))
01242                       {eDest->Emsg("Config", "sched", scopts[i].opname,
01243                                   "value not specified");
01244                        return 1;
01245                       }
01246                         if (*scopts[i].opname == 'i')
01247                            {if (XrdOuca2x::a2tm(*eDest, scopts[i].opmsg, val,
01248                                                 &ppp, scopts[i].minv)) return 1;
01249                            }
01250                    else if (*scopts[i].opname == 's')
01251                            {if (XrdOuca2x::a2sz(*eDest, scopts[i].opmsg, val,
01252                                                 &lpp, scopts[i].minv)) return 1;
01253                             XrdSysThread::setStackSize((size_t)lpp);
01254                             break;
01255                            }
01256                    else if (XrdOuca2x::a2i(*eDest, scopts[i].opmsg, val,
01257                                      &ppp,scopts[i].minv)) return 1;
01258                    *scopts[i].oploc = ppp;
01259                    break;
01260                   }
01261            if (i >= numopts)
01262               eDest->Say("Config warning: ignoring invalid sched option '",val,"'.");
01263            val = Config.GetWord();
01264           }
01265 
01266 // Make sure specified quantities are consistent
01267 //
01268   if (V_maxt > 0)
01269      {if (V_mint > 0 && V_mint > V_maxt)
01270          {eDest->Emsg("Config", "sched mint must be less than maxt");
01271           return 1;
01272          }
01273       if (V_avlt > 0 && V_avlt > V_maxt)
01274          {eDest->Emsg("Config", "sched avlt must be less than maxt");
01275           return 1;
01276          }
01277      }
01278 
01279 // Establish scheduler options
01280 //
01281    if (V_mint > 0 || V_maxt > 0 || V_avlt > 0) setSched = 0;
01282    XrdSched.setParms(V_mint, V_maxt, V_avlt, V_idle);
01283    return 0;
01284 }
01285 
01286 /******************************************************************************/
01287 /*                                  x t m o                                   */
01288 /******************************************************************************/
01289 
01290 /* Function: xtmo
01291 
01292    Purpose:  To parse directive: timeout [read <msd>] [hail <msh>]
01293                                          [idle <msi>] [kill <msk>]
01294 
01295              <msd>    is the maximum number of seconds to wait for pending
01296                       data to arrive before we reschedule the link
01297                       (default is 5 seconds).
01298              <msh>    is the maximum number of seconds to wait for the initial
01299                       data after a connection  (default is 30 seconds)
01300              <msi>    is the minimum number of seconds a connection may remain
01301                       idle before it is closed (default is 5400 = 90 minutes)
01302              <msk>    is the minimum number of seconds to wait after killing a
01303                       connection for it to end (default is 3 seconds)
01304 
01305    Output: 0 upon success or 1 upon failure.
01306 */
01307 
01308 int XrdConfig::xtmo(XrdSysError *eDest, XrdOucStream &Config)
01309 {
01310     char *val;
01311     int  i, ppp, rc;
01312     int  V_read = -1, V_idle = -1, V_hail = -1, V_kill = -1;
01313     static struct tmoopts { const char *opname; int istime; int minv;
01314                             int  *oploc;  const char *etxt;}
01315            tmopts[] =
01316        {
01317         {"read",       1, 1, &V_read, "timeout read"},
01318         {"hail",       1, 1, &V_hail, "timeout hail"},
01319         {"idle",       1, 0, &V_idle, "timeout idle"},
01320         {"kill",       1, 0, &V_kill, "timeout kill"}
01321        };
01322     int numopts = sizeof(tmopts)/sizeof(struct tmoopts);
01323 
01324     if (!(val = Config.GetWord()))
01325        {eDest->Emsg("Config", "timeout option not specified"); return 1;}
01326 
01327     while (val)
01328           {for (i = 0; i < numopts; i++)
01329                if (!strcmp(val, tmopts[i].opname))
01330                    {if (!(val = Config.GetWord()))
01331                        {eDest->Emsg("Config","timeout", tmopts[i].opname,
01332                                    "value not specified");
01333                         return 1;
01334                        }
01335                     rc = (tmopts[i].istime ?
01336                           XrdOuca2x::a2tm(*eDest,tmopts[i].etxt,val,&ppp,
01337                                                  tmopts[i].minv) :
01338                           XrdOuca2x::a2i (*eDest,tmopts[i].etxt,val,&ppp,
01339                                                  tmopts[i].minv));
01340                     if (rc) return 1;
01341                     *tmopts[i].oploc = ppp;
01342                     break;
01343                    }
01344            if (i >= numopts)
01345               eDest->Say("Config warning: ignoring invalid timeout option '",val,"'.");
01346            val = Config.GetWord();
01347           }
01348 
01349 // Set values and return
01350 //
01351    if (V_read >  0) ProtInfo.readWait = V_read*1000;
01352    if (V_hail >= 0) ProtInfo.hailWait = V_hail*1000;
01353    if (V_idle >= 0) ProtInfo.idleWait = V_idle;
01354    XrdLink::setKWT(V_read, V_kill);
01355    return 0;
01356 }
01357   
01358 /******************************************************************************/
01359 /*                                x t r a c e                                 */
01360 /******************************************************************************/
01361 
01362 /* Function: xtrace
01363 
01364    Purpose:  To parse the directive: trace <events>
01365 
01366              <events> the blank separated list of events to trace. Trace
01367                       directives are cummalative.
01368 
01369    Output: 0 upon success or 1 upon failure.
01370 */
01371 
01372 int XrdConfig::xtrace(XrdSysError *eDest, XrdOucStream &Config)
01373 {
01374     char *val;
01375     static struct traceopts {const char *opname; int opval;} tropts[] =
01376        {
01377         {"all",      TRACE_ALL},
01378         {"off",      TRACE_NONE},
01379         {"none",     TRACE_NONE},
01380         {"conn",     TRACE_CONN},
01381         {"debug",    TRACE_DEBUG},
01382         {"mem",      TRACE_MEM},
01383         {"net",      TRACE_NET},
01384         {"poll",     TRACE_POLL},
01385         {"protocol", TRACE_PROT},
01386         {"sched",    TRACE_SCHED}
01387        };
01388     int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
01389 
01390     if (!(val = Config.GetWord()))
01391        {eDest->Emsg("Config", "trace option not specified"); return 1;}
01392     while (val)
01393          {if (!strcmp(val, "off")) trval = 0;
01394              else {if ((neg = (val[0] == '-' && val[1]))) val++;
01395                    for (i = 0; i < numopts; i++)
01396                        {if (!strcmp(val, tropts[i].opname))
01397                            {if (neg)
01398                                if (tropts[i].opval) trval &= ~tropts[i].opval;
01399                                   else trval = TRACE_ALL;
01400                                else if (tropts[i].opval) trval |= tropts[i].opval;
01401                                        else trval = TRACE_NONE;
01402                             break;
01403                            }
01404                        }
01405                    if (i >= numopts)
01406                       eDest->Say("Config warning: ignoring invalid trace option '",val,"'.");
01407                   }
01408           val = Config.GetWord();
01409          }
01410     XrdTrace.What = trval;
01411     return 0;
01412 }

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