45 #include <sys/param.h>
46 #include <sys/resource.h>
47 #include <sys/types.h>
53 #include "XrdVersion.hh"
95 #if defined(__linux__) || defined(__GNU__)
96 #include <netinet/tcp.h>
98 #if defined(__linux__)
99 #include <sys/epoll.h>
102 #include <AvailabilityMacros.h>
143 void TlsError(
const char *tid,
const char *msg,
bool sslmsg)
151 const char *XrdConfig::TraceID =
"Config";
157 #define TS_Xeq(x,m) if (!strcmp(x,var)) return m(eDest, Config);
188 {
for (
int i = 0; i < numP; i++)
189 if (pnum == portVec[i])
190 {tlsVec[i] = isTLS;
return true;}
192 portVec[numP] = pnum; tlsVec[numP] = isTLS;
197 void Reset(
char *ln,
char *pp,
int np=-1,
bool to=
false)
198 {
if (libpath) free(libpath);
200 if (parms) free(parms);
202 memset(portVec, 0,
sizeof(portVec));
204 memset(tlsVec, 0,
sizeof(tlsVec));
211 : Next(0), proname(pn), libpath(ln), parms(pp), numP(1)
212 {memset(portVec, 0,
sizeof(portVec)); port = np;
213 memset(tlsVec, 0,
sizeof(tlsVec)); dotls =
to;
218 if (libpath) free(libpath);
219 if (parms) free(parms);
234 : KingPin(drctv,
theEnv, errR, &myVer)
258 AdminPath= strdup(
"/tmp");
260 PidPath = strdup(
"/tmp");
286 Firstcp = Lastcp = 0;
288 ProtInfo.eDest = &
Log;
291 ProtInfo.Sched = &
Sched;
292 ProtInfo.ConfigFN= 0;
294 ProtInfo.AdmPath = AdminPath;
295 ProtInfo.AdmMode = AdminMode;
296 ProtInfo.theEnv = &
theEnv;
297 ProtInfo.xrdFlags= 0;
300 memset(ProtInfo.rsvd3, 0,
sizeof(ProtInfo.rsvd3));
302 ProtInfo.ConnMax = -1;
303 ProtInfo.readWait = 3*1000;
304 ProtInfo.idleWait = 0;
305 ProtInfo.hailWait =30*1000;
306 ProtInfo.DebugON = 0;
309 ProtInfo.tlsPort = 0;
334 const char *xrdInst=
"XRDINSTANCE=";
336 int retc, NoGo = 0, clPort = -1;
338 char c, buff[512], *dfltProt, *libProt = 0;
342 extern int optind, opterr;
344 int pipeFD[2] = {-1, -1};
345 const char *pidFN = 0;
346 static const int myMaxc = 80;
347 char **urArgv, *myArgv[myMaxc], argBuff[myMaxc*3+8];
348 char *argbP = argBuff, *argbE = argbP+
sizeof(argBuff)-4;
350 int myArgc = 1, urArgc = argc, i;
351 bool noV6, ipV4 =
false, ipV6 =
false, rootChk =
true, optbg =
false;
356 for (
int k = 1; k < argc; k++)
357 {CmdLine +=
' '; CmdLine += argv[k];}
361 retc = strlen(argv[0]);
362 while(retc--)
if (argv[0][retc] ==
'/')
break;
363 myProg = &argv[0][retc+1];
370 {
char *p = dfltProt = strdup(myProg);
371 while(*p && (*p ==
'.' || *p ==
'-')) p++;
373 {
char *dot = index(p,
'.'), *dash = index(p,
'-');
374 if (dot && (dot < dash || !dash)) p = dot;
375 else if (dash) p = dash;
378 if (!strcmp(
"xrootd", dfltProt)) dfltProt[5] = 0;
379 else if (!strcmp(
"cmsd", dfltProt)) dfltProt[3] = 0;
389 {
if (*(argv[i]) ==
'-' && *(argv[i]+1) ==
'+')
390 {
int n = strlen(argv[i]+2), j = i+1, k = 1;
391 if (urArgc == argc) urArgc = i;
392 if (n) memcpy(buff, argv[i]+2, (n > 256 ? 256 : n));
393 strcpy(&(buff[n]),
".argv**");
394 while(j < argc && (*(argv[j]) !=
'-' || *(argv[j]+1) !=
'+')) j++;
395 urArgv =
new char*[j-i+1];
398 while(i < j) urArgv[k++] = argv[i++];
401 strcpy(&(buff[n]),
".argc");
411 if (argc > 1 &&
'-' == *argv[1])
412 while ((c = getopt(urArgc,argv,
":a:A:bc:dhHI:k:l:L:n:N:p:P:R:s:S:vw:W:z"))
413 && ((
unsigned char)c != 0xff))
416 case 'a':
if (AdminPath) free(AdminPath);
417 AdminPath = strdup(optarg);
418 AdminMode = ProtInfo.AdmMode = S_IRWXU;
421 case 'A':
if (AdminPath) free(AdminPath);
422 AdminPath = strdup(optarg);
423 AdminMode = ProtInfo.AdmMode = S_IRWXU | S_IRWXG;
426 case 'b': optbg =
true;
428 case 'c':
if (ConfigFN) free(ConfigFN);
429 ConfigFN = strdup(optarg);
432 ProtInfo.DebugON = 1;
439 case 'I':
if (!strcmp(
"v4", optarg)) {ipV4 =
true; ipV6 =
false;}
440 else if (!strcmp(
"v6", optarg)) {ipV4 =
false; ipV6 =
true;}
441 else {
Log.
Emsg(
"Config",
"Invalid -I argument -",optarg);
446 {
Log.
Emsg(
"Config",
"Invalid -k argument -",optarg);
450 case 'l': LogInfo.
logArg = optarg;
452 case 'L':
if (!*optarg)
453 {
Log.
Emsg(
"Config",
"Protocol library path not specified.");
456 if (libProt) free(libProt);
457 libProt = strdup(optarg);
459 case 'n': myInsName = (!strcmp(optarg,
"anon")||!strcmp(optarg,
"default")
466 case 'P':
if (dfltProt) free(dfltProt);
467 dfltProt = strdup(optarg);
469 case 'R':
if (!(getUG(optarg, myUid, myGid)))
Usage(1);
472 case 's': pidFN = optarg;
474 case 'S': mySitName = optarg;
476 case ':': buff[0] =
'-'; buff[1] =
optopt; buff[2] = 0;
477 Log.
Emsg(
"Config", buff,
"parameter not specified.");
480 case 'v': std::cerr <<XrdVSTRING <<std::endl;
483 case 'w':
if (HomePath) free(HomePath);
484 HomePath = strdup(optarg);
488 case 'W':
if (HomePath) free(HomePath);
489 HomePath = strdup(optarg);
490 HomeMode = S_IRWXU | S_IRGRP | S_IXGRP;
493 case 'z': LogInfo.
hiRes =
true;
497 {
Log.
Emsg(
"Config",
"Long options are not supported.");
500 if (myArgc >= myMaxc || argbP >= argbE)
501 {
Log.
Emsg(
"Config",
"Too many command line arguments.");
504 myArgv[myArgc++] = argbP;
505 *argbP++ =
'-'; *argbP++ =
optopt; *argbP++ = 0;
513 {
Log.
Emsg(
"Config",
"Command line adminpath is not absolute.");
519 if (HomePath && *HomePath !=
'/')
520 {
Log.
Emsg(
"Config",
"Command line home path is not absolute.");
527 if (ConfigFN) setCFG(
true);
533 else if (ipV6){
if (noV6)
Log.
Say(
"Config warning: ipV6 appears to be broken;"
534 " forced ipV6 mode not advised!");
537 else if (noV6)
Log.
Say(
"Config warning: ipV6 is misconfigured or "
538 "unavailable; reverting to ipV4.");
546 if (myGid && setegid(myGid))
547 {
Log.
Emsg(
"Config", errno,
"set effective gid"); exit(17);}
548 if (myUid && seteuid(myUid))
549 {
Log.
Emsg(
"Config", errno,
"set effective uid"); exit(17);}
553 if (rootChk && geteuid() == 0)
554 {
Log.
Emsg(
"Config",
"Security reasons prohibit running as "
555 "superuser; program is terminating.");
561 if (urArgc-
optind+2 >= myMaxc)
562 {
Log.
Emsg(
"Config",
"Too many command line arguments.");
570 ProtInfo.argc = myArgc;
571 ProtInfo.argv = myArgv;
580 if (pipe( pipeFD ) == -1)
581 {
Log.
Emsg(
"Config", errno,
"create a pipe"); exit(17);}
590 auto envName = getenv(
"XRDHOST");
591 const char *ipAddrName;
595 }
else if ((ipAddrName = myIPAddr->
Name(0, &temp))) {
603 ProtInfo.myName = myName.c_str();
604 ProtInfo.myAddr = myIPAddr->
SockAddr();
606 ProtInfo.myProg = myProg;
612 sprintf(buff,
"%s%s %s@%s", xrdInst, myProg, ProtInfo.myInst, myName.c_str());
613 myInstance = strdup(buff);
615 myInstance += strlen(xrdInst);
624 LogInfo.
iName = myInsName;
625 LogInfo.
cfgFn = ConfigFN;
636 {
Log.
Emsg(
"Config",
"Unable to determine host name; ",
637 (temp ? temp :
"reason unknown"),
638 "; execution terminated.");
648 strcpy(buff,
"Starting on ");
660 {
Log.
Emsg(
"Config",myName.c_str(),
"does not appear to be registered in the DNS.");
661 Log.
Emsg(
"Config",
"Verify that the '/etc/hosts' file is correct and "
662 "this machine is registered in DNS.");
663 Log.
Emsg(
"Config",
"Execution continues but connection failures may occur.");
665 }
else if (!(
myDomain = index(myName.c_str(),
'.')))
666 Log.
Say(
"Config warning: this hostname, ", myName.c_str(),
667 ", is registered without a domain qualification.");
671 Firstcp = Lastcp =
new XrdConfigProt(strdup(dfltProt), libProt, 0);
675 Log.
Say(
"++++++ ", myInstance,
" initialization started.");
679 devNull = XrdSysFD_Open(
"/dev/null", O_RDONLY);
681 {
Log.
Emsg(
"Config", errno,
"open '/dev/null' which is required!");
688 {
Log.
Say(
"Config using configuration file ", ConfigFN);
689 ProtInfo.ConfigFN = ConfigFN;
692 if (clPort >= 0) PortTCP = clPort;
693 if (ProtInfo.DebugON)
700 NoGo |= SetupAPath();
705 {
if (!tlsCert) ProtInfo.tlsCtx= 0;
706 else {
Log.
Say(
"++++++ ", myInstance,
" TLS initialization started.");
708 {
Log.
Say(
"------ ",myInstance,
" TLS initialization ended.");
713 Log.
Say(
"------ ",myInstance,
" TLS initialization failed.");
723 {
Log.
Say(
"Config TLS port specification ignored; TLS not configured!");
727 ProtInfo.tlsPort = (PortTLS > 0 ? PortTLS : 0);
743 {
Log.
Emsg(
"Config",
"Unable to determine interface addresses!");
749 if ((myInsName || HomePath)
754 if (!PidFile(pidFN, optbg)) NoGo = 1;
758 if (!NoGo) Manifest(pidFN);
762 if (!NoGo) NoGo = Setup(dfltProt, libProt);
771 if (tmoInfo && !NoGo)
773 if (!theGS)
Log.
Say(
"Config warning: TCP monitoring not enabled; "
774 "tcpmonlib plugin not loaded!");
775 else {tmoInfo->theEnv.PutPtr(
"TcpMon.gStream*", theGS);
776 TcpMonPin = tmoInfo->KingPin.Load(
"TcpMonPin");
786 int status = NoGo ? 1 : 0;
787 if(
write( pipeFD[1], &status,
sizeof( status ) )) {};
794 temp = (NoGo ?
" initialization failed." :
" initialization completed.");
795 sprintf(buff,
"%s:%d", myInstance, PortTCP);
796 Log.
Say(
"------ ", buff, temp);
798 {strcat(buff,
" running ");
816 if (
eDest) dynamic = 1;
830 TS_Xeq(
"adminpath", xapath);
832 TS_Xeq(
"homepath", xhpath);
836 TS_Xeq(
"protocol", xprot);
839 TS_Xeq(
"tcpmonlib", xtcpmon);
843 TS_Xeq(
"tlsciphers", xtlsci);
848 eDest->
Say(
"Config warning: ignoring unknown xrd directive '",var,
"'.");
860 int XrdConfig::ASocket(
const char *path,
const char *fname, mode_t mode)
862 struct sockaddr_un unixvar;
863 int plen = strlen(path), flen = strlen(fname);
867 if ((plen + flen + 3) > (
int)
sizeof(unixvar.sun_path))
868 {
Log.
Emsg(
"Config",
"admin path", path,
"too long");
903 int XrdConfig::ConfigProc()
906 int cfgFD, retc, NoGo = 0;
912 if ( (cfgFD =
open(ConfigFN, O_RDONLY, 0)) < 0)
913 {
Log.
Emsg(
"Config", errno,
"open config file", ConfigFN);
920 while((var =
Config.GetMyFirstWord()))
921 if (!strncmp(var,
"xrd.", 4)
922 || !strcmp (var,
"all.adminpath")
923 || !strcmp (var,
"all.pidpath")
924 || !strcmp (var,
"all.sitename" ))
925 if (ConfigXeq(var+4,
Config)) {
Config.Echo(); NoGo = 1;}
929 if ((retc =
Config.LastError()))
930 NoGo =
Log.
Emsg(
"Config", retc,
"read config file", ConfigFN);
942 XrdInet *XrdConfig::getNet(
int port,
bool isTLS)
944 int the_Opts, the_Blen;
948 for (
int i = 0; i < (int)NetTCP.size(); i++)
949 if (port == NetTCP[i]->Port())
return NetTCP[i];
954 NetTCP.push_back(newNet);
959 {the_Opts = TLS_Opts; the_Blen = TLS_Blen;
961 the_Opts = Net_Opts; the_Blen = Net_Blen;
963 if (the_Opts || the_Blen) newNet->
setDefaults(the_Opts, the_Blen);
971 if (newNet->
BindSD(port,
"tcp") == 0)
return newNet;
980 int XrdConfig::getUG(
char *parm, uid_t &newUid, gid_t &newGid)
987 {
Log.
Emsg(
"Config",
"-R user not specified.");
return 0;}
990 {
if (!(newUid = atol(parm)))
991 {
Log.
Emsg(
"Config",
"-R", parm,
"is invalid");
return 0;}
992 pp = getpwuid(newUid);
994 else pp = getpwnam(parm);
999 {
Log.
Emsg(
"Config", errno,
"retrieve -R user password entry");
1002 if (!(newUid = pp->pw_uid))
1003 {
Log.
Emsg(
"Config",
"-R", parm,
"is still unacceptably a superuser!");
1006 newGid = pp->pw_gid;
1014 void XrdConfig::Manifest(
const char *pidfn)
1017 char envBuff[8192], pwdBuff[2048], manBuff[1024], *pidP, *sP, *xP;
1022 if (!getcwd(pwdBuff,
sizeof(pwdBuff)))
1023 {
Log.
Emsg(
"Config",
"Unable to get current working directory!");
1029 if (HomePath) free(HomePath);
1030 HomePath = strdup(pwdBuff);
1034 strcpy(envBuff, ProtInfo.AdmPath);
1035 envLen = strlen(envBuff);
1036 if (envBuff[envLen-1] !=
'/') {envBuff[envLen] =
'/'; envLen++;}
1037 strcpy(envBuff+envLen,
".xrd/");
1038 xP = envBuff+envLen+5;
1042 if ((sP = getenv(
"XRDCONFIGFN")))
1043 {sprintf(xP,
"=/conf/%s.cf", myProg);
1049 sprintf(xP,
"=/core/%s", myProg);
1054 if ((sP = getenv(
"XRDLOGDIR")))
1055 {sprintf(xP,
"=/logs/%s", myProg);
1062 sprintf(xP,
"=/proc/%s", myProg);
1063 sprintf(manBuff,
"/proc/%d", getpid());
1069 envLen = snprintf(envBuff,
sizeof(envBuff),
"pid=%d&host=%s&inst=%s&ver=%s"
1070 "&home=%s&cfgfn=%s&cwd=%s&apath=%s&logfn=%s",
1071 static_cast<int>(getpid()), ProtInfo.myName,
1072 ProtInfo.myInst, XrdVSTRING, HomePath,
1073 (getenv(
"XRDCONFIGFN") ? getenv(
"XRDCONFIGFN") :
""),
1078 if (pidfn && (Slash = rindex(pidfn,
'/')))
1079 {strncpy(manBuff, pidfn, Slash-pidfn); pidP = manBuff+(Slash-pidfn);}
1080 else {strcpy(manBuff, ProtInfo.AdmPath); pidP = manBuff+strlen(ProtInfo.AdmPath);}
1084 snprintf(pidP,
sizeof(manBuff)-(pidP-manBuff),
"/%s.%s.env",
1085 ProtInfo.myProg, ProtInfo.myInst);
1090 if ((envFD =
open(manBuff, O_WRONLY|O_CREAT|O_TRUNC, 0664)) < 0)
1091 {
Log.
Emsg(
"Config", errno,
"create envfile", manBuff);
1097 if (
write(envFD, envBuff, envLen) < 0)
1098 Log.
Emsg(
"Config", errno,
"write to envfile", manBuff);
1106 bool XrdConfig::PidFile(
const char *clpFN,
bool optbg)
1109 char *ppath, buff[32], pidFN[1200];
1110 const char *xop = 0;
1124 {xop =
"create"; snprintf(pidFN,
sizeof(pidFN),
"%s", ppath); errno = rc;}
1125 else {snprintf(pidFN,
sizeof(pidFN),
"%s/%s.pid", ppath, myProg);
1127 if ((xfd =
open(pidFN, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0)
1129 else {
if (
write(xfd,buff,snprintf(buff,
sizeof(buff),
"%d",
1130 static_cast<int>(getpid()))) < 0) xop =
"write";
1138 if (xop)
Log.
Emsg(
"Config", errno, xop, pidFN);
1146 void XrdConfig::setCFG(
bool start)
1151 if (!ConfigFN || !(*ConfigFN))
1175 if (*ConfigFN !=
'/')
1176 {
char cwdBuff[1024];
1177 if (getcwd(cwdBuff,
sizeof(cwdBuff)-strlen(ConfigFN)-2))
1178 {
int n = strlen(cwdBuff);
1179 if (cwdBuff[n-1] !=
'/') cwdBuff[n++] =
'/';
1180 strcpy(cwdBuff+n, ConfigFN);
1182 ConfigFN = strdup(cwdBuff);
1195 const char *cvec[] = {
"*** ", myProg,
" config from '", ConfigFN,
"':", 0 };
1203 int XrdConfig::setFDL()
1210 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
1211 return Log.
Emsg(
"Config", errno,
"get FD limit");
1215 if (rlim.rlim_max == RLIM_INFINITY || (isStrict && rlim.rlim_max > maxFD))
1216 rlim.rlim_cur = maxFD;
1217 else rlim.rlim_cur = rlim.rlim_max;
1218 #if (defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_5))
1219 if (rlim.rlim_cur > OPEN_MAX) rlim.rlim_max = rlim.rlim_cur = OPEN_MAX;
1221 #if defined(__linux__)
1223 unsigned int epoll_max_fd = (INT_MAX /
sizeof(
struct epoll_event));
1224 if (rlim.rlim_cur > (rlim_t)epoll_max_fd) rlim.rlim_max = rlim.rlim_cur = epoll_max_fd;
1226 if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
1227 return Log.
Emsg(
"Config", errno,
"set FD limit");
1231 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
1232 return Log.
Emsg(
"Config", errno,
"get FD limit");
1236 ProtInfo.ConnMax = rlim.rlim_cur;
1237 sprintf(buff,
"%d", ProtInfo.ConnMax);
1238 Log.
Say(
"Config maximum number of connections restricted to ", buff);
1242 #if !defined( __solaris__ ) && defined(RLIMIT_CORE)
1244 {
if (getrlimit(RLIMIT_CORE, &rlim) < 0)
1245 Log.
Emsg(
"Config", errno,
"get core limit");
1246 else {rlim.rlim_cur = (coreV ? rlim.rlim_max : 0);
1247 if (setrlimit(RLIMIT_CORE, &rlim) < 0)
1248 Log.
Emsg(
"Config", errno,
"set core limit");
1255 #if ( defined(__linux__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) ) && defined(RLIMIT_NPROC)
1259 if (getrlimit(RLIMIT_NPROC, &rlim) < 0)
1260 return Log.
Emsg(
"Config", errno,
"get thread limit");
1264 int nthr =
static_cast<int>(rlim.rlim_cur);
1265 if (nthr < 8192 || ProtInfo.DebugON)
1266 {sprintf(buff,
"%d",
static_cast<int>(rlim.rlim_cur));
1267 Log.
Say(
"Config maximum number of threads restricted to ", buff);
1278 int XrdConfig::Setup(
char *dfltp,
char *libProt)
1281 int xport, protNum = 0;
1285 if (setFDL())
return 1;
1289 #if ( defined(__linux__) || defined(__GNU__) ) && defined(TCP_CORK)
1290 {
int sokFD, setON = 1;
1291 if ((sokFD = socket(PF_INET, SOCK_STREAM, 0)) >= 0)
1293 &setON,
sizeof(setON));
1294 if (setsockopt(sokFD, SOL_TCP, TCP_CORK, &setON,
sizeof(setON)) < 0)
1330 for (
int i = 0; i < cp->
numP; i++)
1333 "configured with a TLS-only port "
1334 "but TLS is not configured!");
1338 xport = (cp->dotls ? PortTLS : PortTCP);
1339 ProtInfo.Port = (cp->port < 0 ? xport : cp->port);
1342 if (cp->port < 0)
return 1;
1343 for (
int i = 1; i < cp->
numP; i++)
1344 if (cp->port == cp->portVec[i]) cp->portVec[i] = -1;
1352 ProtInfo.myName, Firstcp->port,
1353 ProtInfo.myInst, ProtInfo.myProg, mySitName);
1359 xport = (strcmp(
"xroot", Firstcp->proname) ? 0 : Firstcp->port);
1368 while((cp = Firstcp))
1369 {
for (
int i = 0; i < cp->
numP; i++)
1370 {
if (cp->portVec[i] < 0)
continue;
1371 if (!(cp->portVec[i]) && arbNet) theNet = arbNet;
1372 else {theNet = getNet(cp->portVec[i], cp->tlsVec[i]);
1373 if (!theNet)
return 1;
1374 if (!(cp->portVec[i])) arbNet = theNet;
1377 ProtInfo.
Port = theNet->Port();
1378 ProtInfo.NetTCP = theNet;
1379 ProtInfo.WSize = theNet->WSize();
1386 cp->
parms, &ProtInfo,
1388 if (!protNum)
return 1;
1391 if (!strcmp(
"http", cp->
proname) && xport)
1392 {
for (
int i = 0; i < cp->
numP; i++)
1393 {
if (cp->portVec[i] == xport) {xport = 0;
break;}}
1396 Firstcp = cp->
Next;
delete cp;
1408 if (repDest[0] != 0 && repOpts)
1409 {ProtInfo.Stats->Report(repDest, repInt, repOpts);
1424 int XrdConfig::SetupAPath()
1433 else ProtInfo.AdmPath = AdminPath;
1442 {
Log.
Emsg(
"Config", rc,
"create admin path", AdminPath);
1449 if (chmod(AdminPath, AdminMode & ~S_IWGRP))
1450 {
Log.
Emsg(
"Config", errno,
"set permission for admin path", AdminPath);
1458 return ASocket(AdminPath,
"admin", (mode_t)AdminMode);
1465 bool XrdConfig::SetupTLS()
1470 if (!caDir && !caFile && !tlsNoVer)
1472 Log.
Say(
"Config failure: the tlsca directive was not specified!");
1473 else Log.
Say(
"Config failure: the tlsca directive did not specify "
1474 "a certdir or certfile!");
1496 static XrdTlsContext xrdTLS(tlsCert, tlsKey, caDir, caFile, tlsOpts);
1500 if (!xrdTLS.isOK())
return false;
1512 void XrdConfig::Usage(
int rc)
1518 std::cerr <<
"\nUsage: " <<myProg <<
" [-b] [-c <cfn>] [-d] [-h] [-H] [-I {v4|v6}]\n"
1519 "[-k {n|sz|sig}] [-l [=]<fn>] [-n <name>] [-N <hname>] [-p <port>]\n"
1520 "[-P <prot>] [-L <libprot>] [-R] [-s pidfile] [-S site] [-v] [-z]\n"
1521 "[<protocol_options>]" <<std::endl;
1522 _exit(rc > 0 ? rc : 0);
1545 mode_t mode = S_IRWXU;
1550 if (!pval || !pval[0])
1551 {
eDest->
Emsg(
"Config",
"adminpath not specified");
return 1;}
1556 {
eDest->
Emsg(
"Config",
"adminpath not absolute");
return 1;}
1560 if (AdminPath) free(AdminPath);
1561 AdminPath = strdup(pval);
1565 if ((val =
Config.GetWord()) && val[0])
1566 {
if (!strcmp(
"group", val)) mode |= S_IRWXG;
1567 else {
eDest->
Emsg(
"Config",
"invalid admin path modifier -", val);
1571 AdminMode = ProtInfo.AdmMode = mode;
1595 if (!(val =
Config.GetWord()))
1596 {
eDest->
Emsg(
"Config",
"allow type not specified");
return 1;}
1598 if (!strcmp(val,
"host")) ishost = 1;
1599 else if (!strcmp(val,
"netgroup")) ishost = 0;
1600 else {
eDest->
Emsg(
"Config",
"invalid allow type -", val);
1604 if (!(val =
Config.GetWord()))
1605 {
eDest->
Emsg(
"Config",
"allow target name not specified");
return 1;}
1610 if (ishost) Police->AddHost(val);
1611 else Police->AddNetGroup(val);
1636 {
eDest->
Say(
"Config warning: command line homepath cannot be overridden.");
1643 if (HomePath) {free(HomePath); HomePath = 0;}
1648 return (HomePath ? 0 : 1);
1669 static const long long minBSZ = 1024*1024*2+1;
1670 static const long long maxBSZ = 1024*1024*1024;
1675 if (!(val =
Config.GetWord()))
1676 {
eDest->
Emsg(
"Config",
"buffer memory limit not specified");
return 1;}
1678 if (!strcmp(
"maxbsz", val))
1679 {
if (!(val =
Config.GetWord()))
1680 {
eDest->
Emsg(
"Config",
"max buffer size not specified");
return 1;}
1684 if (!(val =
Config.GetWord()))
return 0;
1688 (
long long)1024*1024))
return 1;
1690 if ((val =
Config.GetWord()))
1716 long long minV = 1024, maxV = 1024LL*1024LL;
1720 if ((val =
Config.GetWord()))
1721 {
if (!strcmp(val,
"strict"))
1724 }
else isStrict =
false;
1728 {
eDest->
Emsg(
"Config",
"file descriptor limit not specified");
return 1;}
1733 maxFD =
static_cast<unsigned int>(fdVal);
1767 int i, n, V_keep = -1, V_nodnr = 0, V_istls = 0, V_blen = -1, V_ct = -1;
1768 int V_assumev4 = -1, v_rpip = -1, V_dyndns = -1;
1770 struct netopts {
const char *opname;
int hasarg;
int opval;
1771 int *oploc;
const char *etxt;}
1774 {
"assumev4", 0, 1, &V_assumev4,
"option"},
1775 {
"keepalive", 0, 1, &V_keep,
"option"},
1776 {
"nokeepalive",0, 0, &V_keep,
"option"},
1777 {
"kaparms", 4, 0, &V_keep,
"option"},
1778 {
"buffsz", 1, 0, &V_blen,
"network buffsz"},
1779 {
"cache", 2, 0, &V_ct,
"cache time"},
1780 {
"dnr", 0, 0, &V_nodnr,
"option"},
1781 {
"nodnr", 0, 1, &V_nodnr,
"option"},
1782 {
"dyndns", 0, 1, &V_dyndns,
"option"},
1783 {
"nodyndns", 0, 0, &V_dyndns,
"option"},
1784 {
"routes", 3, 1, 0,
"routes"},
1785 {
"rpipa", 0, 1, &v_rpip,
"rpipa"},
1786 {
"norpipa", 0, 0, &v_rpip,
"norpipa"},
1787 {
"tls", 0, 1, &V_istls,
"option"}
1789 int numopts =
sizeof(ntopts)/
sizeof(
struct netopts);
1791 if (!(val =
Config.GetWord()))
1792 {
eDest->
Emsg(
"Config",
"net option not specified");
return 1;}
1795 {
for (i = 0; i < numopts; i++)
1796 if (!strcmp(val, ntopts[i].opname))
1797 {
if (!ntopts[i].hasarg) *ntopts[i].oploc = ntopts[i].opval;
1798 else {
if (!(val =
Config.GetWord()))
1800 ntopts[i].opname,
"argument missing");
1803 if (ntopts[i].hasarg == 4)
1804 {
if (xnkap(
eDest, val))
return 1;
1807 if (ntopts[i].hasarg == 3)
1808 {
if (!strcmp(val,
"split"))
1810 else if (!strcmp(val,
"common"))
1812 else if (!strcmp(val,
"local"))
1814 else {
eDest->
Emsg(
"Config",
"Invalid routes argument -",val);
1817 if (!(val =
Config.GetWord())|| !(*val))
break;
1818 if (strcmp(val,
"use"))
continue;
1819 if (!(val =
Config.GetWord())|| !(*val))
1820 {
eDest->
Emsg(
"Config",
"network routes i/f names "
1828 if (ntopts[i].hasarg == 2)
1831 *ntopts[i].oploc = n;
1835 *ntopts[i].oploc = (int)llp;
1841 eDest->
Say(
"Config warning: ignoring invalid net option '",val,
"'.");
1842 else if (!val)
break;
1847 {
if (V_blen >= 0) TLS_Blen = V_blen;
1851 if (V_blen >= 0) Net_Blen = V_blen;
1858 {
if (V_dyndns && V_ct < 0) V_ct = 0;
1891 if ((comma = index(val,
','))) {val = comma+1; *comma = 0;}
1898 if (!(karg = val))
return 0;
1899 if ((comma = index(val,
','))) {val = comma+1; *comma = 0;}
1935 if (!val || !val[0])
1936 {
eDest->
Emsg(
"Config",
"pidpath not specified");
return 1;}
1940 if (PidPath) free(PidPath);
1941 PidPath = strdup(val);
1962 {
int rc, istls = 0, pnum = 0;
1963 char *val, cport[32];
1965 do {
if (!(val =
Config.GetWord()))
1966 {
eDest->
Emsg(
"Config",
"tcp port not specified");
return 1;}
1967 if (strcmp(
"tls", val) || istls)
break;
1971 strncpy(cport, val,
sizeof(cport)-1); cport[
sizeof(cport)-1] =
'\0';
1973 if ((val =
Config.GetWord()) && !strcmp(
"if", val))
1975 ProtInfo.myInst, myProg)) <= 0)
1976 {
if (!rc)
Config.noEcho();
return (rc < 0);}
1979 if (istls) PortTLS = pnum;
1980 else PortTCP = PortUDP = pnum;
2007 char *val, *parms, *lib, proname[64], buff[2048];
2011 do {
if (!(val =
Config.GetWord()))
2012 {
eDest->
Emsg(
"Config",
"protocol name not specified");
return 1;}
2013 if (dotls || strcmp(
"tls", val))
break;
2017 if (strlen(val) >
sizeof(proname)-1)
2018 {
eDest->
Emsg(
"Config",
"protocol name is too long");
return 1;}
2019 strcpy(proname, val);
2021 if ((val = index(proname,
':')))
2026 if (!(val =
Config.GetWord()))
2027 {
eDest->
Emsg(
"Config",
"protocol library not specified");
return 1;}
2028 if (!strcmp(
"*", val)) lib = 0;
2029 else if (*val ==
'+')
2030 {
if (strcmp(val,
"+port"))
2031 {
eDest->
Emsg(
"Config",
"invalid library specification -",val);
2034 if ((cpp = Firstcp))
2035 do {
if (!strcmp(proname, cpp->
proname))
2036 {
if (cpp->
AddPort(portnum, dotls))
return 0;
2037 eDest->
Emsg(
"Config",
"port add limit exceeded!");
2040 }
while((cpp = cpp->
Next));
2041 eDest->
Emsg(
"Config",
"protocol",proname,
"not previously defined!");
2044 else lib = strdup(val);
2049 if (!lib && Firstcp && strcmp(proname, Firstcp->proname))
2051 snprintf(eBuff,
sizeof(eBuff),
"the %s protocol is '%s' not '%s'; "
2052 "assuming you meant '%s'",
2053 (Firstcp->libpath ?
"assigned" :
"builtin"),
2054 Firstcp->proname, proname, Firstcp->proname);
2055 eDest->
Say(
"Config warning: ", eBuff,
" but please correct "
2056 "the following directive!");
2057 snprintf(proname,
sizeof(proname),
"%s", Firstcp->proname);
2061 if (!
Config.GetRest(buff,
sizeof(buff)))
2062 {
eDest->
Emsg(
"Config",
"Too many parms for protocol", proname);
2065 parms = (*buff ? strdup(buff) : 0);
2067 if ((cpp = Firstcp))
2068 do {
if (!strcmp(proname, cpp->
proname))
2069 {cpp->
Reset(lib, parms, portnum, dotls);
2072 }
while((cpp = cpp->
Next));
2074 cpp =
new XrdConfigProt(strdup(proname), lib, parms, portnum, dotls);
2075 if (!lib) {cpp->
Next = Firstcp; Firstcp = cpp;
2076 if (!Lastcp) Lastcp = cpp;
2078 else {
if (Lastcp) Lastcp->
Next = cpp;
2108 static struct repopts {
const char *opname;
int opval;} rpopts[] =
2123 int i, neg, numopts =
sizeof(rpopts)/
sizeof(
struct repopts);
2126 if (!(val =
Config.GetWord()))
2127 {
eDest->
Emsg(
"Config",
"report parameters not specified");
return 1;}
2131 if (repDest[0]) {free(repDest[0]); repDest[0] = 0;}
2132 if (repDest[1]) {free(repDest[1]); repDest[1] = 0;}
2138 if ((cp = (
char *)index(val,
',')))
2140 {
eDest->
Emsg(
"Config",
"malformed report destination -",val);
return 1;}
2141 else { repDest[1] = cp+1; *cp =
'\0';}
2144 for (i = 0; i < 2; i++)
2145 {
if (!(val = repDest[i]))
break;
2146 if (*val !=
'/' && (!(cp = index(val, (
int)
':')) || !atoi(cp+1)))
2147 {
eDest->
Emsg(
"Config",
"report dest port missing or invalid in",val);
2150 repDest[i] = strdup(val);
2155 if (repDest[0] && repDest[1] && !strcmp(repDest[0], repDest[1]))
2156 {
eDest->
Emsg(
"Config",
"Warning, report dests are identical.");
2157 free(repDest[1]); repDest[1] = 0;
2163 if (!strcmp(
"every", val))
2164 {
if (!(val =
Config.GetWord()))
2165 {
eDest->
Emsg(
"Config",
"report every value not specified");
return 1;}
2173 {
if (!strcmp(val,
"off")) repOpts = 0;
2174 else {
if ((neg = (val[0] ==
'-' && val[1]))) val++;
2175 for (i = 0; i < numopts; i++)
2176 {
if (!strcmp(val, rpopts[i].opname))
2177 {
if (neg) repOpts &= ~rpopts[i].opval;
2178 else repOpts |= rpopts[i].opval;
2183 eDest->
Say(
"Config warning: ignoring invalid report option '",val,
"'.");
2228 int V_mint = -1, V_maxt = -1, V_idle = -1, V_avlt = -1;
2229 struct schedopts {
const char *opname;
int minv;
int *oploc;
2230 const char *opmsg;} scopts[] =
2232 {
"stksz", 0, 0,
"sched stksz"},
2233 {
"mint", 1, &V_mint,
"sched mint"},
2234 {
"maxt", 1, &V_maxt,
"sched maxt"},
2235 {
"avlt", 1, &V_avlt,
"sched avlt"},
2236 {
"core", 1, 0,
"sched core"},
2237 {
"idle", 0, &V_idle,
"sched idle"}
2239 int numopts =
sizeof(scopts)/
sizeof(
struct schedopts);
2241 if (!(val =
Config.GetWord()))
2242 {
eDest->
Emsg(
"Config",
"sched option not specified");
return 1;}
2245 {
for (i = 0; i < numopts; i++)
2246 if (!strcmp(val, scopts[i].opname))
2247 {
if (!(val =
Config.GetWord()))
2248 {
eDest->
Emsg(
"Config",
"sched", scopts[i].opname,
2249 "value not specified");
2252 if (*scopts[i].opname ==
'i')
2254 &ppp, scopts[i].minv))
return 1;
2256 else if (*scopts[i].opname ==
'c')
2257 {
if (!strcmp(
"asis", val)) coreV = -1;
2258 else if (!strcmp(
"max", val)) coreV = 1;
2259 else if (!strcmp(
"off", val)) coreV = 0;
2260 else {
eDest->
Emsg(
"Config",
"invalid sched core value -",val);
2264 else if (*scopts[i].opname ==
's')
2266 &lpp, scopts[i].minv))
return 1;
2271 &ppp,scopts[i].minv))
return 1;
2272 *scopts[i].oploc = ppp;
2276 eDest->
Say(
"Config warning: ignoring invalid sched option '",val,
"'.");
2283 {
if (V_mint > 0 && V_mint > V_maxt)
2284 {
eDest->
Emsg(
"Config",
"sched mint must be less than maxt");
2287 if (V_avlt > 0 && V_avlt > V_maxt)
2288 {
eDest->
Emsg(
"Config",
"sched avlt must be less than maxt");
2318 if (!(val =
Config.GetWord()))
2319 {
eDest->
Emsg(
"Config",
"sitename value not specified");
return 1;}
2321 if (mySitName)
eDest->
Emsg(
"Config",
"sitename already specified, using '",
2344 char *val, parms[2048];
2349 if ((val =
Config.GetWord()))
2350 {
if (!strcmp(val,
"++"))
2359 {
eDest->
Emsg(
"Config",
"tcpmonlib not specified");
return 1;}
2364 {
eDest->
Emsg(
"Config",
"tcpmonlib path is not absolute");
return 1;}
2372 if (!
Config.GetRest(parms,
sizeof(parms)))
2373 {
eDest->
Emsg(
"Config",
"tcpmonlib parameters too long");
return 1;}
2381 tmoInfo->KingPin.Add(path.c_str(), (*parms ? parms : 0), push);
2410 if (!(val =
Config.GetWord()))
2411 {
eDest->
Emsg(
"Config",
"tls cert path not specified");
return 1;}
2414 {
eDest->
Emsg(
"Config",
"tls cert path not absolute");
return 1;}
2416 if (tlsCert) free(tlsCert);
2417 tlsCert = strdup(val);
2418 if (tlsKey) free(tlsKey);
2421 if (!(val =
Config.GetWord()))
return 0;
2424 {tlsKey = strdup(val);
2425 if (!(val =
Config.GetWord()))
return 0;
2428 do {
if (!strcmp(val,
"detail")) SSLmsgs =
true;
2429 else if (!strcmp(val,
"nodetail")) SSLmsgs =
false;
2430 else if (!strcmp(val,
"hsto" ))
2431 {
if (!(val =
Config.GetWord()))
2432 {
eDest->
Emsg(
"Config",
"tls hsto value not specified");
2439 else {
eDest->
Emsg(
"Config",
"invalid tls option -",val);
return 1;}
2440 }
while ((val =
Config.GetWord()));
2477 char *val, **cadest, kword[16];
2481 if (!(val =
Config.GetWord()))
2482 {
eDest->
Emsg(
"Config",
"tlsca parameter not specified");
return 1;}
2485 if (!strcmp(val,
"noverify"))
2487 if (caDir) {free(caDir); caDir = 0;}
2488 if (caFile) {free(caFile); caFile = 0;}
2494 do {
if (!strcmp(val,
"proxies") || !strcmp(
"noproxies", val))
2500 if (strlen(val) >= (
int)
sizeof(kword))
2501 {
eDest->
Emsg(
"Config",
"Invalid tlsca parameter -", val);
2506 if (!(val =
Config.GetWord()))
2507 {
eDest->
Emsg(
"Config",
"tlsca", kword,
"value not specified");
2510 if ((isdir = !strcmp(kword,
"certdir"))
2511 || !strcmp(kword,
"certfile"))
2513 {
eDest->
Emsg(
"Config",
"tlsca",kword,
"path is not absolute.");
2516 cadest = (isdir ? &caDir : &caFile);
2517 if (*cadest) free(*cadest);
2518 *cadest = strdup(val);
2520 else if (!strcmp(kword,
"crlcheck"))
2524 else if ( strcmp(val,
"external"))
2525 {
eDest->
Emsg(
"Config",
"Invalid tlsca crlcheck "
2530 else if (!strcmp(kword,
"log"))
2531 {
if (!strcmp(val,
"off"))
2533 else if (!strcmp(val,
"failure"))
2535 else {
eDest->
Emsg(
"Config",
"Invalid tlsca log argument -",val);
2539 else if (!strcmp(kword,
"refresh"))
2542 if (rt < 60) rt = 60;
2543 else if (rt % 60) rt += 60;
2547 else if (!strcmp(kword,
"verdepth"))
2552 else {
eDest->
Emsg(
"Config",
"invalid tlsca option -",kword);
return 1;}
2554 }
while((val =
Config.GetWord()));
2574 char *val, *ciphers;
2576 if (!(val =
Config.GetWord()))
2577 {
eDest->
Emsg(
"Config",
"tlsciphers parameter not specified");
return 1;}
2579 ciphers = strdup(val);
2581 if ((val =
Config.GetWord()))
2582 {
eDest->
Emsg(
"Config",
"Invalid tlsciphers argument -",val);
2616 int V_read = -1, V_idle = -1, V_hail = -1, V_kill = -1;
2617 struct tmoopts {
const char *opname;
int istime;
int minv;
2618 int *oploc;
const char *etxt;}
2621 {
"read", 1, 1, &V_read,
"timeout read"},
2622 {
"hail", 1, 1, &V_hail,
"timeout hail"},
2623 {
"idle", 1, 0, &V_idle,
"timeout idle"},
2624 {
"kill", 1, 0, &V_kill,
"timeout kill"}
2626 int numopts =
sizeof(tmopts)/
sizeof(
struct tmoopts);
2628 if (!(val =
Config.GetWord()))
2629 {
eDest->
Emsg(
"Config",
"timeout option not specified");
return 1;}
2632 {
for (i = 0; i < numopts; i++)
2633 if (!strcmp(val, tmopts[i].opname))
2634 {
if (!(val =
Config.GetWord()))
2635 {
eDest->
Emsg(
"Config",
"timeout", tmopts[i].opname,
2636 "value not specified");
2639 rc = (tmopts[i].istime ?
2645 *tmopts[i].oploc = ppp;
2649 eDest->
Say(
"Config warning: ignoring invalid timeout option '",val,
"'.");
2655 if (V_read > 0) ProtInfo.readWait = V_read*1000;
2656 if (V_hail >= 0) ProtInfo.hailWait = V_hail*1000;
2657 if (V_idle >= 0) ProtInfo.idleWait = V_idle;
2679 static struct traceopts {
const char *opname;
int opval;} tropts[] =
2696 int i, neg, trval = 0, numopts =
sizeof(tropts)/
sizeof(
struct traceopts);
2698 if (!(val =
Config.GetWord()))
2699 {
eDest->
Emsg(
"Config",
"trace option not specified");
return 1;}
2701 {
if (!strcmp(val,
"off")) trval = 0;
2702 else {
if ((neg = (val[0] ==
'-' && val[1]))) val++;
2703 for (i = 0; i < numopts; i++)
2704 {
if (!strcmp(val, tropts[i].opname))
2706 if (tropts[i].opval) trval &= ~tropts[i].opval;
2708 else if (tropts[i].opval) trval |= tropts[i].opval;
2714 eDest->
Say(
"Config warning: ignoring invalid trace option '",val,
"'.");
void Usage(const char *msg)
static XrdSysError eDest(0,"crypto_")
int open(const char *path, int oflag,...)
ssize_t write(int fildes, const void *buf, size_t nbyte)
#define TLS_SET_VDEPTH(cOpts, vdv)
#define TLS_SET_HSTO(cOpts, hstv)
#define TLS_SET_REFINT(cOpts, refi)
void Set(int maxmem=-1, int minw=-1)
void Reset(char *ln, char *pp, int np=-1, bool to=false)
XrdConfigProt(char *pn, char *ln, char *pp, int np=-1, bool to=false)
bool AddPort(int pnum, bool isTLS)
int ConfigXeq(char *var, XrdOucStream &Config, XrdSysError *eDest=0)
int Configure(int argc, char **argv)
int BindSD(int port, const char *contype="tcp")
static void SetAssumeV4(bool newVal)
static int Setup(int maxfds, int idlewt)
static void setKWT(int wkSec, int kwSec)
const sockaddr * SockAddr()
const char * Name(const char *eName=0, const char **eText=0)
static void SetCache(int keeptime)
static void SetDynDNS(bool onoff)
static void SetRPIPA(bool rval)
static int GetIF(XrdOucTList **ifList, const char **eText=0)
static void Routing(netType nettype)
static void SetMsgs(XrdSysError *erp)
static bool SetIFNames(char *ifnames)
static void SetFQN(const char *fqn)
static int ProtoID(const char *pName)
static int ServPort(const char *sName, bool isUDP=false, const char **eText=0)
void setDomain(const char *dname)
void setDefaults(int options, int buffsz=0)
void PutInt(const char *varname, long value)
static int Export(const char *Var, const char *Val)
void * GetPtr(const char *varname)
void PutPtr(const char *varname, void *value)
void Put(const char *varname, const char *value)
static bool configLog(XrdSysError &eDest, configLogInfo &logInfo)
static const char * Set(const char *name, int maxlen=15)
static XrdOucString * Capture()
const char * c_str() const
static char * parseHome(XrdSysError &eDest, XrdOucStream &Config, int &mode)
static const mode_t pathMode
static char * genPath(const char *path, const char *inst, const char *psfx=0)
static int ReLink(const char *path, const char *target, mode_t mode=0)
static const char * InstName(int TranOpt=0)
static int doIf(XrdSysError *eDest, XrdOucStream &Config, const char *what, const char *hname, const char *nname, const char *pname)
static int makePath(char *path, mode_t mode, bool reset=false)
static bool PidFile(XrdSysError &eDest, const char *path)
static void makeHome(XrdSysError &eDest, const char *inst)
static void Undercover(XrdSysError &eDest, int noLog, int *pipeFD=0)
static int a2i(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
static int a2sz(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
static int a2p(XrdSysError &, const char *ptype, const char *val, bool anyOK=true)
static int Setup(int numfd)
static const int PortoMax
static int Port(const char *lname, const char *pname, char *parms, XrdProtocol_Config *pi)
static int Load(const char *lname, const char *pname, char *parms, XrdProtocol_Config *pi, bool istls)
int Stats(char *buff, int blen, int do_sync=0)
void setParms(int minw, int maxw, int avlt, int maxi, int once=0)
void setNproc(const bool limlower)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
XrdSysLogger * logger(XrdSysLogger *lp=0)
void AddMsg(const char *msg)
int ParseKeep(const char *arg)
static void setDebug(XrdSysError *erp)
static void setStackSize(size_t stsz, bool force=false)
static int FmtUname(char *buff, int blen)
XrdOucPinKing< XrdTcpMonPin > KingPin
XrdTcpMonInfo(const char *drctv, const char *cfn, XrdSysError &errR)
static const int crlRS
Bits to shift vdept.
static void SetDefaultCiphers(const char *ciphers)
static const uint64_t servr
This is a server context.
static const uint64_t nopxy
Do not allow proxy certs.
static const uint64_t logVF
Log verify failures.
static const uint64_t crlFC
Full crl chain checking.
static const uint64_t crlON
Enables crl checking.
static const uint64_t crlRF
Mask to isolate crl refresh in min.
static void SetMsgCB(msgCB_t cbP)
static const int dbgSIO
Turn debugging in for socket I/O.
static const int dbgSOK
Turn debugging in for socket operations.
static const int dbgALL
Turn debugging for everything.
static const int dbgCTX
Turn debugging in for context operations.
static void SetDebug(int opts, XrdSysLogger *logP=0)
XrdVERSIONINFODEF(myVersion, cmsclient, XrdVNUMBER, XrdVERSION)
static INT to(const char *buffer)