27 #include "Xrd/XrdBuffer.hh" 28 #include "Xrd/XrdScheduler.hh" 30 #include "XrdOuc/XrdOucStream.hh" 53 XPDLOC(PMGR,
"ExportCpCmd")
55 XrdOucString *ccs = (XrdOucString *)s;
57 if (ccs->length() > 0) *ccs +=
",";
83 #if !defined(__APPLE__) 111 XPDLOC(ALL,
"Admin::Process")
116 TRACEP(p, REQ,
"req id: " << type <<
" ("<<
156 emsg +=
"Invalid type: ";
162 response->Send(kXR_InvalidRequest, emsg.c_str());
174 XPDLOC(ALL,
"Admin::Config")
178 XPDERR(
"problems parsing file ");
183 msg = (rcf) ?
"re-configuring" :
"configuring";
184 TRACE(ALL, msg.c_str());
188 TRACE(ALL,
"additional paths which can be browsed by all users: ");
189 std::list<XrdOucString>::iterator is =
fExportPaths.begin();
193 TRACE(ALL,
"allowed/supported copy commands: "<<
fCpCmds);
203 char *val, XrdOucStream *cfg,
bool rcf)
205 XPDLOC(SMGR,
"Admin::DoDirective")
211 if (d->
fName ==
"exportpath") {
213 }
else if (d->
fName ==
"cpcmd") {
226 XPDLOC(SMGR,
"Admin::DoDirectiveExportPath")
232 TRACE(ALL,
"val: "<<val);
235 XrdOucString tkns(val), tkn;
237 while ((from = tkns.tokenize(tkn, from,
' ')) != STR_NPOS) {
241 val = cfg->GetWord();
253 XPDLOC(SMGR,
"Admin::DoDirectiveCpCmd")
259 XrdOucString
proto, cpcmd, fmt;
260 bool canput = 0, isfmt = 0, rm = 0;
263 XrdOucString tkn(val);
264 if (proto.length() <= 0) {
266 if (proto.beginswith(
'-')) {
271 }
else if (cpcmd.length() <= 0) {
273 }
else if (tkn.beginswith(
"put:")) {
275 if (tkn ==
"put:1") canput = 1;
276 }
else if (tkn.beginswith(
"fmt:")) {
277 fmt.assign(tkn, 4, -1);
286 val = cfg->GetWord();
292 }
else if (cpcmd.length() > 0 && fmt.length() > 0) {
295 fmt.insert(cpcmd, 0);
298 TRACE(ALL,
"incomplete information: ignoring!");
314 XPDLOC(ALL,
"Admin::QueryMssUrl")
323 TRACEP(p, DBG,
"sending: "<<msg);
326 response->Send((
void *)msg.c_str(), msg.length()+1);
337 XPDLOC(ALL,
"Admin::QueryROOTVersions")
344 TRACEP(p, DBG,
"sending: "<<msg);
347 response->Send((
void *)msg.c_str(), msg.length()+1);
358 XPDLOC(ALL,
"Admin::SetROOTVersion")
364 const char *t = p->
Argp() ? (
const char *) p->
Argp()->buff :
"default";
366 XrdOucString tag(t,len);
371 if (tag.beginswith(
"u:")) {
373 usr.erase(usr.rfind(
' '));
374 usr.replace(
"u:",
"");
376 tag.erase(0,tag.find(
' ') + 1);
378 TRACEP(p, REQ,
"usr: "<<usr<<
", version tag: "<< tag);
384 if (usr.length() > 0) {
386 if (usr.find(
':') != STR_NPOS) {
388 grp.erase(grp.rfind(
':'));
389 usr.erase(0,usr.find(
':') + 1);
393 grp = g ? g->
Name() :
"default";
397 usr.insert(
"not allowed to change settings for usr '", 0);
399 TRACEP(p, XERR, usr.c_str());
400 response->Send(kXR_InvalidRequest, usr.c_str());
406 XrdOucString emsg(
"user not found or not allowed: ");
408 TRACEP(p, XERR, emsg.c_str());
409 response->Send(kXR_InvalidRequest, emsg.c_str());
418 if (!r && tag ==
"default") {
429 " for {client, group} = {"<<usr<<
", "<<grp<<
"} ("<<c<<
")");
433 XrdOucString buf(
"u:");
445 tag.insert(
"tag '", 0);
446 tag +=
"' not found in the list of available ROOT versions on some worker nodes";
447 TRACEP(p, XERR, tag.c_str());
448 response->Send(kXR_InvalidRequest, tag.c_str());
451 tag.insert(
"tag '", 0);
452 tag +=
"' not found in the list of available ROOT versions";
453 TRACEP(p, XERR, tag.c_str());
454 response->Send(kXR_InvalidRequest, tag.c_str());
466 XPDLOC(ALL,
"Admin::QueryWorkers")
472 XrdOucString sbuf(1024);
476 char *buf = (
char *) sbuf.c_str();
477 int len = sbuf.length() + 1;
478 TRACEP(p, DBG,
"sending: "<<buf);
481 response->Send(buf, len);
492 XPDLOC(ALL,
"Admin::GetWorkers")
503 TRACEP(p, XERR,
"session ID not found: "<<psid);
504 response->Send(kXR_InvalidRequest,
"session ID not found");
507 int pid = xps->SrvPID();
508 TRACEP(p, REQ,
"request from session "<<pid);
511 XrdOucString wrks(
"");
520 response->Send(kXR_InvalidRequest,
"GetWorkers failed");
526 char *buf = (
char *) wrks.c_str();
527 int len = wrks.length() + 1;
528 TRACEP(p, DBG,
"sending: "<<buf);
532 response->Send(buf, len);
535 response->Send(kXR_InvalidRequest,
"GetWorkers failed");
548 XPDLOC(ALL,
"Admin::SetGroupProperties")
555 char *grp =
new char[len+1];
556 memcpy(grp, p->
Argp()->buff, len);
558 TRACEP(p, DBG,
"request to change priority for group '"<< grp<<
"'");
562 TRACEP(p, XERR,
"received group does not match the user's one");
563 response->Send(kXR_InvalidRequest,
564 "SetGroupProperties: received group does not match the user's one");
575 XPDFORM(buf,
"%s %d", grp, priority);
578 TRACEP(p, XERR,
"problem sending message on the pipe");
579 response->Send(kXR_ServerError,
580 "SetGroupProperties: problem sending message on the pipe");
587 TRACEP(p, REQ,
"priority for group '"<< grp<<
"' has been set to "<<priority);
603 XPDLOC(ALL,
"Admin::SendMsgToUser")
611 std::list<XrdProofdClient *>::iterator i;
617 TRACEP(p, XERR,
"no message");
618 response->Send(kXR_InvalidRequest,
"SendMsgToUser: no message");
622 XrdOucString cmsg((
const char *)p->
Argp()->buff, len);
624 if (cmsg.beginswith(
"u:")) {
626 int isp = cmsg.find(
' ');
627 if (isp != STR_NPOS) {
628 usr.assign(cmsg, 2, isp-1);
629 cmsg.erase(0, isp+1);
631 if (usr.length() > 0) {
632 TRACEP(p, REQ,
"request for user: '"<<usr<<
"'");
641 TRACEP(p, XERR,
"target client not found");
642 response->Send(kXR_InvalidRequest,
643 "SendMsgToUser: target client not found");
649 if (cmsg.length() <= 0) {
651 TRACEP(p, XERR,
"no message after user specification");
652 response->Send(kXR_InvalidRequest,
653 "SendMsgToUser: no message after user specification");
659 if (usr.length() > 0) {
660 if (tgtclnt != p->
Client()) {
661 TRACEP(p, XERR,
"not allowed to send messages to usr '"<<usr<<
"'");
662 response->Send(kXR_InvalidRequest,
663 "SendMsgToUser: not allowed to send messages to specified usr");
667 TRACEP(p, XERR,
"not allowed to send messages to connected users");
668 response->Send(kXR_InvalidRequest,
669 "SendMsgToUser: not allowed to send messages to connected users");
673 if (usr.length() <= 0) tgtclnt = 0;
691 XPDLOC(ALL,
"Admin::QuerySessions")
696 XrdOucString notmsg, msg;
702 if (notmsg.length() > 0) {
704 response->Send(kXR_attn,
kXPD_srvmsg, 0, (
char *) notmsg.c_str(), notmsg.length());
707 TRACEP(p, DBG,
"sending: "<<msg);
710 response->Send((
void *)msg.c_str(), msg.length()+1);
721 XPDLOC(ALL,
"Admin::QueryLogPaths")
730 XrdOucString stag, master, user, ord, buf;
733 buf.assign(p->
Argp()->buff,0,len-1);
734 int im = buf.find(
"|master:");
735 int iu = buf.find(
"|user:");
736 int io = buf.find(
"|ord:");
738 stag.erase(stag.find(
"|"));
739 if (im != STR_NPOS) {
740 master.assign(buf, im + strlen(
"|master:"));
741 master.erase(master.find(
"|"));
743 if (iu != STR_NPOS) {
744 user.assign(buf, iu + strlen(
"|user:"));
745 user.erase(user.find(
"|"));
747 if (io != STR_NPOS) {
748 ord.assign(buf, iu + strlen(
"|ord:"));
749 ord.erase(user.find(
"|"));
751 if (stag.beginswith(
'*'))
754 TRACEP(p, DBG,
"master: "<<master<<
", user: "<<user<<
", ord: "<<ord<<
", stag: "<<stag);
761 TRACEP(p, XERR,
"query sess logs: client for '"<<user<<
"' not found");
762 response->Send(kXR_InvalidRequest,
"QueryLogPaths: query log: client not found");
766 XrdOucString tag = (stag ==
"" && ridx >= 0) ?
"last" : stag;
768 TRACEP(p, XERR,
"query sess logs: session tag not found");
769 response->Send(kXR_InvalidRequest,
"QueryLogPaths: query log: session tag not found");
776 if (master.length() <= 0) {
778 rmsg += tag; rmsg +=
"|";
789 DIR *dir = opendir(sdir.c_str());
791 XrdOucString msg(
"cannot open dir ");
792 msg += sdir; msg +=
" (errno: "; msg += errno; msg +=
")";
793 TRACEP(p, XERR, msg.c_str());
794 response->Send(kXR_InvalidRequest, msg.c_str());
799 XrdOucString wfile(sdir);
800 wfile +=
"/.workers";
801 bool ismaster = (access(wfile.c_str(), F_OK) == 0) ? 1 : 0;
804 XrdOucString xo, logtag, xf;
805 int ilog, idas, iund1, iund2;
806 struct dirent *ent = 0;
807 while ((ent = (
struct dirent *)readdir(dir))) {
808 if (!strcmp(ent->d_name,
".") || !strcmp(ent->d_name,
".."))
continue;
809 XPDFORM(xf,
"%s/%s", sdir.c_str(), (
const char *) ent->d_name);
811 if (stat(xf.c_str(), &st) != 0)
continue;
812 if (!S_ISREG(st.st_mode))
continue;
814 if (xo.matches(
"*-*-*-*-*.log") <= 0 && xo.matches(
"*-*-*-*-*.valgrind.log") <= 0)
continue;
815 TRACEP(p, ALL,
"xf: "<<xf<<
"; st_mode: "<<st.st_mode);
817 if ((ilog = xo.find(
".log")) != STR_NPOS) {
818 xo.replace(
".log",
"");
822 iund1 = xo.find(
"__");
823 if (iund1 != STR_NPOS) {
824 iund2 = xo.rfind(
"__");
825 if ((iund2 != STR_NPOS) && (iund2 != iund1)) {
828 logtag.erase(0, iund1+2);
832 if ((idas = xo.find(
'-')) != STR_NPOS) xo.erase(0, idas + 1);
833 if ((idas = xo.find(
'-')) != STR_NPOS) xo.erase(idas);
834 if (ord.length() > 0 && (ord == xo)) {
837 if (ismaster && !broadcast) {
838 if (!strncmp(ent->d_name,
"master-", 7)) recordinfo = 1;
844 rmsg +=
"|"; rmsg += xo;
845 if (logtag !=
"") { rmsg +=
'('; rmsg += logtag; rmsg +=
')'; }
846 rmsg +=
" proof://"; rmsg +=
fMgr->
Host(); rmsg +=
':';
848 rmsg += sdir; rmsg +=
'/'; rmsg += ent->d_name;
856 if (broadcast && ismaster) {
857 XrdOucString msg(tag);
861 msg += client->
User();
867 }
else if (ismaster) {
870 FILE *
f = fopen(wfile.c_str(),
"r");
873 while (fgets(ln,
sizeof(ln), f)) {
874 if (ln[strlen(ln)-1] ==
'\n')
875 ln[strlen(ln)-1] = 0;
877 char *ps = strchr(ln,
' ');
882 char *po = strchr(ps,
' ');
886 char *pp = strchr(po,
' ');
891 rmsg +=
"|"; rmsg += po; rmsg +=
" ";
892 if (master.length() > 0) {
896 rmsg += ln; rmsg +=
'/';
899 char *ppl = strrchr(pp,
'/');
900 pp = (ppl) ? ppl : pp;
903 bool ismst = (strstr(pp,
"master-")) ? 1 : 0;
906 XrdOucString msg(stag);
927 response->Send((
void *) rmsg.c_str(), rmsg.length()+1);
938 XPDLOC(ALL,
"Admin::CleanupSessions")
954 all = (what == 1) ? 1 : 0;
963 buf = p->
Argp()->buff;
964 len = (len < 9) ? len : 8;
970 usr =
new char[len+1];
971 memcpy(usr, buf, len);
974 char *grp = strstr(usr,
":");
983 TRACEP(p, REQ,
"superuser, cleaning usr: "<< usr);
987 TRACEP(p, REQ,
"superuser, all sessions cleaned");
992 int len = strlen(tgtclnt->
User()) + 1;
993 usr =
new char[len+1];
994 memcpy(usr, tgtclnt->
User(), len);
1000 TRACEP(p, DBG,
"client '"<<usr<<
"' has no sessions - do nothing");
1005 const char *lab = hard ?
"hard-reset" :
"soft-reset";
1009 XPDFORM(cmsg,
"CleanupSessions: %s: signalling active sessions for termination", lab);
1010 response->Send(kXR_attn,
kXPD_srvmsg, (
char *) cmsg.c_str(), cmsg.length());
1014 XPDFORM(cmsg,
"CleanupSessions: %s: cleaning up client: requested by: %s", lab, p->
Link()->ID);
1022 XPDFORM(cmsg,
"CleanupSessions: %s: forwarding the reset request to next tier(s) ", lab);
1023 response->Send(kXR_attn,
kXPD_srvmsg, 0, (
char *) cmsg.c_str(), cmsg.length());
1034 while (twait-- > 0 &&
1037 XPDFORM(cmsg,
"CleanupSessions: %s: wait %d more seconds for completion ...", lab, twait);
1038 response->Send(kXR_attn,
kXPD_srvmsg, 0, (
char *) cmsg.c_str(), cmsg.length());
1058 XPDLOC(ALL,
"Admin::SetSessionAlias")
1068 TRACEP(p, XERR,
"session ID not found: "<<psid);
1069 response->Send(kXR_InvalidRequest,
"SetSessionAlias: session ID not found");
1074 const char *msg = (
const char *) p->
Argp()->buff;
1080 if (len > 0 && msg) {
1083 XrdOucString alias(xps->Alias());
1084 TRACEP(p, DBG,
"session alias set to: "<<alias);
1100 XPDLOC(ALL,
"Admin::SetSessionTag")
1109 TRACEP(p, XERR,
"session ID not found: "<<psid);
1110 response->Send(kXR_InvalidRequest,
"SetSessionTag: session ID not found");
1115 const char *msg = (
const char *) p->
Argp()->buff;
1121 if (len > 0 && msg) {
1124 XrdOucString tag(xps->Tag());
1125 TRACEP(p, DBG,
"session tag set to: "<<tag);
1141 XPDLOC(ALL,
"Admin::ReleaseWorker")
1150 TRACEP(p, XERR,
"session ID not found: "<<psid);
1151 response->Send(kXR_InvalidRequest,
"ReleaseWorker: session ID not found");
1156 const char *msg = (
const char *) p->
Argp()->buff;
1162 if (len > 0 && msg) {
1163 xps->RemoveWorker(msg);
1164 TRACEP(p, DBG,
"worker \""<<msg<<
"\" released");
1182 if (!s || (len = strlen(s)) <= 0)
return 0;
1187 if (c ==
'(' || c ==
')' || c ==
'{' || c ==
'}' || c ==
';') {
1200 XPDLOC(ALL,
"Admin::Exec")
1203 #if !defined(__APPLE__) 1204 const char *cmds[] = {
"rm",
"ls",
"more",
"grep",
"tail",
"md5sum",
"stat",
"find" };
1206 const char *cmds[] = {
"rm",
"ls",
"more",
"grep",
"tail",
"md5",
"stat",
"find" };
1208 const char *actcmds[] = {
"remove",
"access",
"open",
"open",
"open",
"open",
"stat",
"find"};
1218 emsg =
"client instance not found";
1220 response->Send(kXR_InvalidRequest, emsg.c_str());
1226 if (action < kRm || action >
kFind) {
1227 emsg =
"unknown action type: ";
1230 response->Send(kXR_InvalidRequest, emsg.c_str());
1236 XrdOucString msg, node, path, opt;
1237 if (dlen > 0 && p->
Argp()->buff) {
1238 msg.assign((
const char *)p->
Argp()->buff, 0, dlen);
1242 if ((from = msg.tokenize(node, from,
'|')) != -1) {
1243 if ((from = msg.tokenize(path, from,
'|')) != -1) {
1244 from = msg.tokenize(opt, from,
'|');
1246 emsg =
"'path' not found in message";
1249 emsg =
"'node' not found in message";
1251 if (emsg.length() > 0) {
1253 response->Send(kXR_InvalidRequest, emsg.c_str());
1260 emsg =
"none of the characters '(){};' are allowed in path string ("; emsg += path; emsg +=
")";
1262 response->Send(kXR_InvalidRequest, emsg.c_str());
1266 emsg =
"none of the characters '(){};' are allowed in opt string ("; emsg += opt; emsg +=
")";
1268 response->Send(kXR_InvalidRequest, emsg.c_str());
1277 if (node ==
"all") {
1279 emsg =
"action cannot be run in mode 'all' - running on master only";
1280 response->Send(kXR_attn,
kXPD_srvmsg, 2, (
char *)emsg.c_str(), emsg.length());
1284 }
else if (!islocal) {
1289 TRACEP(p, HDBG,
"sending request to "<<u);
1292 if (!(xrsp =
fMgr->
NetMgr()->
Send(u.c_str(),
type, msg.c_str(), 0, response, 0, action))) {
1293 TRACEP(p, XERR,
"problems sending request to "<<u);
1297 result.assign((
const char *) xrsp->
GetData(), 0, xrsp->
DataLen());
1298 }
else if (action ==
kRm) {
1309 if (node !=
"all" && !islocal) {
1311 if (result.length() > 0) {
1312 response->Send(result.c_str());
1321 XrdOucString cmd, pfx(
fMgr->
Host());
1325 if (node !=
"all") {
1327 emsg =
"Node: "; emsg += pfx;
1329 response->Send(kXR_attn,
kXPD_srvmsg, 2, (
char *)emsg.c_str(), emsg.length());
1338 XrdOucString fullpath(path);
1340 bool haswild = (fullpath.find(
'*') != STR_NPOS) ? 1 : 0;
1341 int check = (action ==
kMore || action ==
kTail ||
1343 if ((action ==
kRm || action ==
kLs) && haswild) check = 0;
1347 fullpath, check, sandbox, &st, emsg)) != 0) {
1349 emsg = cmds[action];
1350 emsg +=
": cannot ";
1351 emsg += actcmds[action];
1354 emsg +=
"': No such file or directory";
1355 }
else if (rccp == -3) {
1356 emsg = cmds[action];
1357 emsg +=
": cannot stat ";
1359 emsg +=
": errno: ";
1360 emsg += (int) errno;
1361 }
else if (rccp == -4) {
1362 emsg = cmds[action];
1365 emsg +=
": Is not a regular file";
1368 response->Send(kXR_InvalidRequest, emsg.c_str());
1373 if (action ==
kRm) {
1377 emsg =
"not allowed to rm with wild cards on path: ";
1380 response->Send(kXR_InvalidRequest, emsg.c_str());
1383 if ((
int) st.st_uid != tgtclnt->
UI().
fUid || (int) st.st_gid != tgtclnt->
UI().
fGid) {
1384 emsg =
"rm on path: ";
1386 emsg +=
" requires ownership; path owned by: (";
1387 emsg += (int) st.st_uid; emsg +=
",";
1388 emsg += (
int) st.st_gid; emsg +=
")";
1390 response->Send(kXR_InvalidRequest, emsg.c_str());
1395 const char *sbdir[5] = {
"queries",
"packages",
"cache",
"datasets",
"data"};
1396 while (fullpath.endswith(
'/'))
1397 fullpath.erasefromend(1);
1398 XrdOucString sball(tgtclnt->
Sandbox()->
Dir()), sball1 = sball;
1399 sball +=
"/*"; sball1 +=
"/*/";
1400 if (fullpath == sball || fullpath == sball1) {
1401 emsg =
"removing all sandbox directory is not allowed: ";
1404 response->Send(kXR_InvalidRequest, emsg.c_str());
1409 if (fullpath.endswith(sbdir[kk])) {
1410 emsg =
"removing a basic sandbox directory is not allowed: ";
1413 response->Send(kXR_InvalidRequest, emsg.c_str());
1421 if (opt.length() <= 0) opt =
"-f";
1422 cmd +=
" "; cmd += opt;
1423 cmd +=
" "; cmd += fullpath;
1428 XrdOucString rederr;
1432 if (opt.length() <= 0) opt =
"-C";
1450 emsg =
"undefined action: ";
1452 emsg =
" - protocol error!";
1454 response->Send(kXR_ServerError, emsg.c_str());
1457 if (action != kFind) {
1458 if (cmd.length() > 0) cmd +=
" ";
1459 if (opt.length() > 0) { cmd += opt; cmd +=
" ";}
1462 cmd +=
" "; cmd += fullpath;
1463 if (opt.length() > 0) { cmd +=
" "; cmd += opt; }
1465 if (rederr.length() > 0) cmd += rederr;
1470 if (
ExecCmd(p, response, action, cmd.c_str(), emsg) != 0) {
1472 response->Send(kXR_ServerError, emsg.c_str());
1478 response->Send(emsg.c_str());
1481 response->Send(
"OK");
1501 int action,
const char *cmd, XrdOucString &emsg)
1503 XPDLOC(ALL,
"Admin::ExecCmd")
1506 XrdOucString pfx = emsg;
1510 if (!cmd || strlen(cmd) <= 0) {
1511 emsg =
"undefined command!";
1518 emsg =
"cannot create the pipe";
1523 TRACEP(p, DBG,
"forking to execute in the private sandbox");
1525 if (!(pid =
fMgr->
Sched()->Fork(
"adminexeccmd"))) {
1530 emsg =
"SetUserEnvironment did not return OK";
1534 if (action ==
kStat) {
1536 if ((stat(cmd, &st)) != 0) {
1537 if (errno == ENOENT) {
1538 emsg +=
"stat: cannot stat `";
1540 emsg +=
"': No such file or directory";
1542 emsg +=
"stat: cannot stat ";
1544 emsg +=
": errno: ";
1545 emsg += (int) errno;
1550 int islink = S_ISLNK(st.st_mode);
1551 snprintf(msg, 256,
"%ld %ld %d %d %d %lld %ld %d", (
long)st.st_dev,
1552 (
long)st.st_ino, st.st_mode, (
int)(st.st_uid),
1553 (
int)(st.st_gid), (kXR_int64)st.st_size, st.st_mtime, islink);
1558 FILE *fp = popen(cmd,
"r");
1560 emsg =
"could not run '"; emsg += cmd; emsg +=
"'";
1564 int pfxlen = pfx.length();
1568 int bufsiz = 1024, left = bufsiz - 1, lines = 0;
1569 while (fgets(line,
sizeof(line), fp)) {
1571 int llen = strlen(line);
1574 if (lines == 1 && action ==
kMd5sum) {
1575 if (line[llen-1] ==
'\n') {
1576 line[llen-1] =
'\0';
1579 #if !defined(__APPLE__) 1581 XrdOucString sl(line);
1582 sl.tokenize(emsg, 0,
' ');
1585 XrdOucString sl(line), tkn;
1587 while ((from = sl.tokenize(tkn, from,
' ')) != STR_NPOS) {
1594 if ((llen + pfxlen) > left) {
1596 if (buf[len-1] ==
'\n') buf[len-1] =
'\0';
1598 emsg =
"error sending message to requester";
1608 memcpy(buf+len, pfx.c_str(), pfxlen);
1613 memcpy(buf+len, line, llen);
1617 if (lines > 0 && !(lines % 10)) {
1619 if (p->
Link()->Peek(&b[0], 1, 0) == 1) {
1628 if (buf[len-1] ==
'\n') buf[len-1] =
'\0';
1630 emsg =
"error sending message to requester";
1636 if ((rcpc = pclose(fp)) == -1) {
1637 emsg =
"could not close the command pipe";
1640 if (WEXITSTATUS(rcpc) != 0) {
1641 emsg =
"failure: return code: ";
1642 emsg += (int) WEXITSTATUS(rcpc);
1651 if (pp.
Post(-1, emsg.c_str()) != 0) rc = 1;
1655 if (pp.
Post(0, emsg.c_str()) != 0) rc = 1;
1663 emsg =
"forking failed - errno: "; emsg += (int) errno;
1668 TRACEP(p, DBG,
"forking OK: wait for information");
1671 int prc = 0, rst = -1;
1673 while (rst < 0 && rc >= 0) {
1674 while ((prc = pp.
Poll(60)) > 0) {
1676 if (pp.
Recv(msg) != 0) {
1677 emsg =
"error receiving message from pipe";
1686 if (buf.length() <= 0) {
1687 emsg =
"error reading string from received message";
1695 if (buf.length() <= 0) {
1696 emsg =
"error reading string from received message";
1707 emsg =
"timeout from poll";
1709 }
else if (prc < 0) {
1710 emsg =
"error from poll - errno: "; emsg += -prc;
1723 XrdOucString &fullpath,
int check,
bool &sandbox,
1724 struct stat *st, XrdOucString &emsg)
1726 if (!sbdir || strlen(sbdir) <= 0) {
1727 emsg =
"CheckPath: sandbox dir undefined!";
1732 XrdOucString path(fullpath);
1734 if (path.beginswith(
'/')) {
1736 if (fullpath.beginswith(sbdir)) sandbox = 1;
1738 if (path.beginswith(
"../")) path.erase(0,2);
1739 if (path.beginswith(
"./") || path.beginswith(
"~/")) path.erase(0,1);
1740 if (!path.beginswith(
"/")) path.insert(
'/',0);
1745 fullpath.replace(
"//",
"/");
1748 if (!sandbox && !superuser) {
1750 std::list<XrdOucString>::iterator si =
fExportPaths.begin();
1752 if (path.beginswith((*si).c_str())) {
1759 emsg =
"CheckPath: not allowed to run the requested action on ";
1765 if (check > 0 && st) {
1767 if (stat(fullpath.c_str(), st) != 0) {
1768 if (errno == ENOENT) {
1776 if ((check == 2) && !S_ISREG(st->st_mode))
return -4;
1788 XPDLOC(ALL,
"Admin::GetFile")
1798 emsg =
"client instance not found";
1800 response->Send(kXR_InvalidRequest, emsg.c_str());
1807 if (dlen > 0 && p->
Argp()->buff) {
1808 path.assign((
const char *)p->
Argp()->buff, 0, dlen);
1809 if (path.length() <= 0) {
1810 TRACEP(p, XERR,
"path missing!");
1811 response->Send(kXR_InvalidRequest,
"path missing!");
1818 XrdOucString fullpath(path);
1819 bool sandbox = 0, check = 2;
1823 fullpath, check, sandbox, &st, emsg)) != 0) {
1825 emsg =
"Cannot open `";
1827 emsg +=
"': No such file or directory";
1828 }
else if (rccp == -3) {
1829 emsg =
"Cannot stat `";
1831 emsg +=
"': errno: ";
1832 emsg += (int) errno;
1833 }
else if (rccp == -4) {
1835 emsg +=
" is not a regular file";
1838 response->Send(kXR_InvalidRequest, emsg.c_str());
1845 emsg =
"cannot create the pipe for internal communications";
1847 response->Send(kXR_InvalidRequest, emsg.c_str());
1851 TRACEP(p, DBG,
"forking to execute in the private sandbox");
1853 if (!(pid =
fMgr->
Sched()->Fork(
"admingetfile"))) {
1859 emsg =
"SetUserEnvironment did not return OK";
1864 int fd =
open(fullpath.c_str(), O_RDONLY);
1866 emsg =
"cannot open file: ";
1868 emsg +=
" - errno:";
1869 emsg += (int) errno;
1871 response->Send(kXR_ServerError, emsg.c_str());
1877 snprintf(sizmsg, 64,
"%lld", (kXR_int64) st.st_size);
1878 response->Send((
const char *) &sizmsg[0]);
1879 TRACEP(p, XERR,
"size is "<<sizmsg<<
" bytes");
1882 const int kMAXBUF = 16384;
1885 lseek(fd, pos, SEEK_SET);
1887 while (rc == 0 && pos < st.st_size) {
1888 off_t left = st.st_size - pos;
1889 if (left > kMAXBUF) left = kMAXBUF;
1892 while ((siz =
read(fd, &buf[0], left)) < 0 && errno == EINTR)
1894 if (siz < 0 || siz != left) {
1895 emsg =
"error reading from file: errno: ";
1896 emsg += (int) errno;
1902 if ((src = response->Send(kXR_attn,
kXPD_msg, (
void *)&buf[0], left)) != 0) {
1903 emsg =
"error reading from file: errno: ";
1911 if (pp.
Post(0,
"") != 0) {
1921 response->Send(kXR_attn,
kXPD_srvmsg, 0, (
char *) emsg.c_str(), emsg.length());
1929 if (pp.
Post(-1, emsg.c_str()) != 0) rc = 1;
1932 if (pp.
Post(1,
"") != 0) rc = 1;
1941 emsg =
"forking failed - errno: "; emsg += (int) errno;
1943 response->Send(kXR_ServerError, emsg.c_str());
1948 TRACEP(p, DBG,
"forking OK: execution will continue in the child process");
1951 int prc = 0, rst = 0;
1953 while (rst == 0 && rc >= 0) {
1954 while ((prc = pp.
Poll(60)) > 0) {
1956 if (pp.
Recv(msg) != 0) {
1957 emsg =
"error receiving message from pipe";
1968 if (emsg.length() <= 0) {
1969 emsg =
"error reading string from received message";
1973 }
else if (rst > 0) {
1979 emsg =
"timeout from poll";
1981 }
else if (prc < 0) {
1982 emsg =
"error from poll - errno: "; emsg += -prc;
1988 TRACEP(p, DBG,
"execution over: "<< ((rc == 0) ?
"ok" :
"failed"));
1999 XPDLOC(ALL,
"Admin::PutFile")
2009 emsg =
"client instance not found";
2011 response->Send(kXR_InvalidRequest, emsg.c_str());
2016 kXR_int64 size = -1;
2018 XrdOucString cmd, path, ssiz, opt;
2019 if (dlen > 0 && p->
Argp()->buff) {
2020 cmd.assign((
const char *)p->
Argp()->buff, 0, dlen);
2021 if (cmd.length() <= 0) {
2022 TRACEP(p, XERR,
"input buffer missing!");
2023 response->Send(kXR_InvalidRequest,
"input buffer missing!");
2027 if ((from = cmd.tokenize(path, from,
' ')) < 0) {
2028 TRACEP(p, XERR,
"cannot resolve path!");
2029 response->Send(kXR_InvalidRequest,
"cannot resolve path!");
2032 if ((from = cmd.tokenize(ssiz, from,
' ')) < 0) {
2033 TRACEP(p, XERR,
"cannot resolve word with size!");
2034 response->Send(kXR_InvalidRequest,
"cannot resolve word with size!");
2038 size = atoll(ssiz.c_str());
2040 TRACEP(p, XERR,
"cannot resolve size!");
2041 response->Send(kXR_InvalidRequest,
"cannot resolve size!");
2045 cmd.tokenize(opt, from,
' ');
2047 TRACEP(p, DBG,
"path: '"<<path<<
"'; size: "<<size<<
" bytes; opt: '"<<opt<<
"'");
2050 kXR_unt32 openflags = O_WRONLY | O_TRUNC | O_CREAT;
2051 kXR_unt32 modeflags = 0600;
2055 XrdOucString fullpath(path);
2056 bool sandbox = 0, check = 1;
2060 fullpath, check, sandbox, &st, emsg)) != 0) {
2064 emsg +=
"' exists but cannot be stat: errno: ";
2065 emsg += (int) errno;
2069 response->Send(kXR_InvalidRequest, emsg.c_str());
2074 if (opt ==
"force") {
2075 openflags = O_WRONLY | O_TRUNC;
2079 emsg +=
"' exists; user option 'force' to override it";
2081 response->Send(kXR_InvalidRequest, emsg.c_str());
2089 emsg =
"cannot create the pipe for internal communications";
2091 response->Send(kXR_InvalidRequest, emsg.c_str());
2095 TRACEP(p, DBG,
"forking to execute in the private sandbox");
2097 if (!(pid =
fMgr->
Sched()->Fork(
"adminputfile"))) {
2102 emsg =
"SetUserEnvironment did not return OK";
2106 int fd =
open(fullpath.c_str(), openflags, modeflags);
2108 emsg =
"cannot open file: ";
2110 emsg +=
" - errno: ";
2111 emsg += (int) errno;
2113 response->Send(kXR_ServerError, emsg.c_str());
2118 response->Send(
"OK");
2124 emsg =
"cannot get buffer to read data out";
2128 kXR_int64 filesize = 0, left = 0;
2129 while (rc == 0 && filesize < size) {
2130 left = size - filesize;
2131 if (left > kMAXBUF) left = kMAXBUF;
2133 TRACEP(p, ALL,
"receiving "<<left<<
" ...");
2134 if ((rc = p->
GetData(
"data", argp->buff, left))) {
2136 emsg =
"cannot read data out";
2143 char *
b = argp->buff;
2147 while ((w =
write(fd, b, r)) < 0 && errno == EINTR)
2150 emsg =
"error writing to unit: ";
2159 if (pp.
Post(0,
"") != 0) {
2171 response->Send(kXR_attn,
kXPD_srvmsg, 0, (
char *) emsg.c_str(), emsg.length());
2178 if (pp.
Post(-1, emsg.c_str()) != 0) rc = 1;
2181 if (pp.
Post(1,
"") != 0) rc = 1;
2189 emsg =
"forking failed - errno: "; emsg += (int) errno;
2191 response->Send(kXR_ServerError, emsg.c_str());
2196 TRACEP(p, DBG,
"forking OK: execution will continue in the child process");
2199 int prc = 0, rst = 0;
2201 while (rst == 0 && rc >= 0) {
2202 while ((prc = pp.
Poll(60)) > 0) {
2204 if (pp.
Recv(msg) != 0) {
2205 emsg =
"error receiving message from pipe";
2216 if (emsg.length() <= 0) {
2217 emsg =
"error reading string from received message";
2221 }
else if (rst > 0) {
2227 emsg =
"timeout from poll";
2229 }
else if (prc < 0) {
2230 emsg =
"error from poll - errno: "; emsg += -prc;
2236 TRACEP(p, DBG,
"execution over: "<< ((rc == 0) ?
"ok" :
"failed"));
2247 XPDLOC(ALL,
"Admin::CpFile")
2257 emsg =
"client instance not found";
2259 response->Send(kXR_InvalidRequest, emsg.c_str());
2265 XrdOucString buf, src, dst, fmt;
2266 if (dlen > 0 && p->
Argp()->buff) {
2267 buf.assign((
const char *)p->
Argp()->buff, 0, dlen);
2268 if (buf.length() <= 0) {
2269 TRACEP(p, XERR,
"input buffer missing!");
2270 response->Send(kXR_InvalidRequest,
"input buffer missing!");
2274 if ((from = buf.tokenize(src, from,
' ')) < 0) {
2275 TRACEP(p, XERR,
"cannot resolve src path!");
2276 response->Send(kXR_InvalidRequest,
"cannot resolve src path!");
2279 if ((from = buf.tokenize(dst, from,
' ')) < 0) {
2280 TRACEP(p, XERR,
"cannot resolve dst path!");
2281 response->Send(kXR_InvalidRequest,
"cannot resolve dst path!");
2285 fmt.assign(buf, from);
2287 TRACEP(p, DBG,
"src: '"<<src<<
"'; dst: '"<<dst<<
"'; fmt: '"<<fmt<<
"'");
2292 if (usrc.Proto.length() > 0 && usrc.Proto !=
"file") {
2295 TRACEP(p, XERR,
"protocol for source file not supported");
2296 response->Send(kXR_InvalidRequest,
"protocol for source file not supported");
2300 if (usrc.Proto ==
"file") src = usrc.File;
2303 if (udst.Proto.length() > 0 && udst.Proto !=
"file") {
2306 TRACEP(p, XERR,
"protocol for destination file not supported");
2307 response->Send(kXR_InvalidRequest,
"protocol for destination file not supported");
2311 if (udst.Proto ==
"file") dst = udst.File;
2318 if (!locsrc && !locdst) {
2320 TRACEP(p, XERR,
"At least destination or source must be local");
2321 response->Send(kXR_InvalidRequest,
"At least destination or source must be local");
2323 }
else if (!locdst) {
2327 TRACEP(p, XERR,
"not allowed to create destination file with the chosen protocol");
2328 response->Send(kXR_InvalidRequest,
"not allowed to create destination file with the chosen protocol");
2333 }
else if (!locsrc) {
2344 XrdOucString srcpath(src), dstpath(dst);
2345 bool sbsrc = 0, sbdst = 0;
2346 struct stat stsrc, stdst;
2347 int rccpsrc = 0, rccpdst = 0;
2348 if (loc2loc || loc2rem) {
2350 srcpath, 2, sbsrc, &stsrc, emsg)) != 0) {
2351 if (rccpsrc == -2) {
2353 emsg +=
": cannot open `";
2355 emsg +=
"': No such file or directory";
2356 }
else if (rccpsrc == -3) {
2358 emsg +=
": cannot stat ";
2360 emsg +=
": errno: ";
2361 emsg += (int) errno;
2362 }
else if (rccpsrc == -4) {
2366 emsg +=
": Is not a regular file";
2369 response->Send(kXR_InvalidRequest, emsg.c_str());
2373 if (loc2loc || rem2loc) {
2375 dstpath, 0, sbdst, &stdst, emsg)) != 0) {
2376 if (rccpdst == -2) {
2378 emsg +=
": cannot open `";
2380 emsg +=
"': No such file or directory";
2381 }
else if (rccpdst == -3) {
2383 emsg +=
": cannot stat ";
2385 emsg +=
": errno: ";
2386 emsg += (int) errno;
2387 }
else if (rccpdst == -4) {
2391 emsg +=
": Is not a regular file";
2394 response->Send(kXR_InvalidRequest, emsg.c_str());
2400 if (fmt.length() <= 0) {
2403 if (!fmt.beginswith(xc->
fCmd)) {
2405 fmt.insert(xc->
fCmd, 0);
2407 if (fmt.find(
"%s") == STR_NPOS) {
2408 fmt.insert(
" %s %s", -1);
2416 TRACEP(p, DBG,
"Executing command: " << cmd);
2421 emsg =
"cannot create the pipe";
2423 response->Send(kXR_ServerError, emsg.c_str());
2428 TRACEP(p, DBG,
"forking to execute in the private sandbox");
2430 if (!(pid =
fMgr->
Sched()->Fork(
"admincpfile"))) {
2435 emsg =
"SetUserEnvironment did not return OK";
2439 FILE *fp = popen(cmd.c_str(),
"r");
2441 emsg =
"could not run '"; emsg += cmd; emsg +=
"'";
2446 while (fgets(line,
sizeof(line), fp)) {
2448 int llen = strlen(line);
2449 if (llen > 0 && line[llen-1] ==
'\n') {
2450 line[llen-1] =
'\0';
2455 response->Send(kXR_attn,
kXPD_srvmsg, 4, (
char *) &line[0], llen) != 0) {
2456 emsg =
"error sending message to requester";
2462 if (p->
Link()->Peek(&b[0], 1, 0) == 1) {
2467 if (pp.
Post(0,
"") != 0) {
2474 if ((rcpc = pclose(fp)) == -1) {
2475 emsg =
"error while trying to close the command pipe";
2478 if (WEXITSTATUS(rcpc) != 0) {
2479 emsg =
"return code: ";
2480 emsg += (int) WEXITSTATUS(rcpc);
2484 char cp[1] = {
'\n'};
2485 if (response->Send(kXR_attn,
kXPD_srvmsg, 3, (
char *) &cp[0], 1) != 0) {
2486 emsg =
"error sending progress notification to requester";
2494 if (pp.
Post(-1, emsg.c_str()) != 0) rc = 1;
2498 if (pp.
Post(1,
"") != 0) rc = 1;
2506 emsg =
"forking failed - errno: "; emsg += (int) errno;
2511 TRACEP(p, DBG,
"forking OK: wait for execution");
2514 int prc = 0, rst = 0;
2516 while (rst == 0 && rc >= 0) {
2517 while ((prc = pp.
Poll(60)) > 0) {
2519 if (pp.
Recv(msg) != 0) {
2520 emsg =
"error receiving message from pipe";;
2531 if (emsg.length() <= 0)
2532 emsg =
"error reading string from received message";
2533 }
else if (rst == 1) {
2539 emsg =
"timeout from poll";
2541 }
else if (prc < 0) {
2542 emsg =
"error from poll - errno: "; emsg += -prc;
2548 TRACEP(p, DBG,
"execution over: "<< ((rc == 0) ?
"ok" :
"failed"));
2551 emsg.insert(
"failure: ", 0);
2553 response->Send(kXR_ServerError, emsg.c_str());
2555 response->Send(
"OK");
const char * Name() const
double read(const std::string &file_name)
reading
int QueryLogPaths(XrdProofdProtocol *p)
Handle request for log paths.
int GetFile(XrdProofdProtocol *p)
Handle request for sending a file.
int Poll(int to=-1)
Poll over the read pipe for to secs; return whatever poll returns.
int ReleaseWorker(XrdProofdProtocol *p)
Handle request for releasing a worker.
int Exec(XrdProofdProtocol *p)
Handle request of cleaning parts of the sandbox.
int QuerySessions(XrdProofdProtocol *p)
Handle request for list of sessions.
int GetWorkers(XrdOucString &workers, XrdProofdProofServ *, const char *)
Get a list of workers from the available resource broker.
int ExecCmd(XrdProofdProtocol *p, XrdProofdResponse *r, int action, const char *cmd, XrdOucString &emsg)
Low-level execution handler.
XrdProofdProofServMgr * SessionMgr() const
int CheckPath(bool superuser, const char *sbdir, XrdOucString &fullpath, int check, bool &sandbox, struct stat *st, XrdOucString &emsg)
Handle request for sending a file.
double write(int n, const std::string &file_name, const std::string &vector_type, int compress=0)
writing
static const char * AdminMsgType(int type)
Translates the admin message type in a human readable string.
XrdROOT * DefaultVersion() const
XrdProofdNetMgr * NetMgr() const
int Process(XrdProofdProtocol *p, int type)
Process admin request.
int DoDirectiveClass(XrdProofdDirective *, char *val, XrdOucStream *cfg, bool rcf)
Generic class directive processor.
int QueryMssUrl(XrdProofdProtocol *p)
Handle request for the URL to the MSS attached to the cluster.
#define TRACE(Flag, Args)
int DoDirective(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
Update the priorities of the active sessions.
XrdScheduler * Sched() const
void Broadcast(XrdProofdClient *c, const char *msg)
Broadcast message 'msg' to the connected instances of client 'clnt' or to all connected instances if ...
int SetSessionTag(XrdProofdProtocol *p)
Handle request for setting the session tag.
int CheckForbiddenChars(const char *s)
Check is 's' contains any of the forbidden chars '(){};' Return 0 if OK (no forbidden chars)...
virtual int ExportInfo(XrdOucString &)
Fill sbuf with some info about our current status.
short int ProofProtocol() const
static XrdBuffer * GetBuff(int quantum, XrdBuffer *argp=0)
Allocate a buffer to handle quantum bytes; if argp points to an existing buffer, its size is checked ...
struct ClientRequestHdr header
int Recv(XpdMsg &msg)
Recv message from the pipe.
XrdClientMessage * Send(const char *url, int type, const char *msg, int srvtype, XrdProofdResponse *r, bool notify=0, int subtype=-1)
Broadcast request to known potential sub-nodes.
XrdProofSched * ProofSched() const
XrdProofGroupMgr * GroupsMgr() const
const char * User() const
char * ReadLogPaths(const char *url, const char *stag, int isess)
Get log paths from next tier; used in multi-master setups Returns 0 in case of error.
XrdOucString ExportSessions(XrdOucString &emsg, XrdProofdResponse *r=0)
Return a string describing the existing sessions.
int Broadcast(int type, const char *msg, const char *usr=0, XrdProofdResponse *r=0, bool notify=0, int subtype=-1)
Broadcast request to known potential sub-nodes.
int QueryROOTVersions(XrdProofdProtocol *p)
Handle request for list of ROOT versions.
int QueryWorkers(XrdProofdProtocol *p)
Handle request for getting the list of potential workers.
static void Form(XrdOucString &s, const char *fmt, int ns, const char *ss[5], int ni, int ii[6], int np, void *pp[5], int nu=0, unsigned int ui=0)
Recreate the string according to 'fmt', the up to 5 'const char *', up to 6 'int' arguments...
void TerminateSessions(XrdProofdClient *c, const char *msg, int srvtype)
Terminate sessions of client 'clnt' or to of all clients if clnt == 0.
const char * NameSpace() const
#define kXPROOFSRVALIASMAX
int PutFile(XrdProofdProtocol *p)
Handle request for recieving a file.
std::list< XrdOucString > fExportPaths
int DoDirectiveExportPath(char *, XrdOucStream *, bool)
Process 'exportpath' directives eg: xpd.exportpath /tmp/data /data2/data.
XrdROOT * GetVersion(const char *tag)
Return pointer to the ROOT version corresponding to 'tag' or 0 if not found.
XrdProofdSandbox * Sandbox() const
XrdOucString ExportVersions(XrdROOT *def)
Return a string describing the available versions, with the default version 'def' markde with a '*'...
struct XPClientProofRequest proof
const char * Host() const
#define TRACEP(p, act, x)
XrdProofdClientMgr * ClientMgr() const
int SetGroupProperties(XrdProofdProtocol *p)
Handle request for setting group properties.
XrdProofdAdmin(XrdProofdManager *mgr, XrdProtocol_Config *pi, XrdSysError *e)
Constructor.
int GuessTag(XrdOucString &tag, int ridx=1)
Guess session tag completing 'tag' (typically "-<pid>") by scanning the active session file or the se...
int GetData(const char *dtype, char *buff, int blen)
Get data from the open link.
XrdProofGroup * GetUserGroup(const char *usr, const char *grp=0)
Returns the instance of the first group to which this user belongs; if grp != 0, return the instance ...
XrdOucHash< XpdAdminCpCmd > fAllowedCpCmds
int CpFile(XrdProofdProtocol *p)
Handle request for copy files from / to the sandbox.
XrdROOTMgr * ROOTMgr() const
static int ExportCpCmd(const char *k, XpdAdminCpCmd *cc, void *s)
Decrease active session counters on worker w.
void RegisterDirectives()
Register directives for configuration.
int SetSessionAlias(XrdProofdProtocol *p)
Handle request for setting the session alias.
int Config(bool rcf=0)
Run configuration and parse the entered config directives.
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
const char * EffectiveUser() const
const char * PoolURL() const
int Process(XrdLink *lp)
Process the information received on the active link.
#define XPD_SETRESP(p, x)
int CleanupSessions(XrdProofdProtocol *p)
Handle request of.
R__EXTERN C unsigned int sleep(unsigned int seconds)
bool IsLocal(const char *host, bool checkport=0)
Check if 'host' is this local host.
XrdProofdPriorityMgr * PriorityMgr() const
int SetROOTVersion(XrdProofdProtocol *p)
Handle request for changing the default ROOT version.
static void ReleaseBuff(XrdBuffer *argp)
Release a buffer previously allocated via GetBuff.
int GetWorkers(XrdProofdProtocol *p)
Handle request for getting the best set of workers.
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
XrdProofdClient * GetClient(const char *usr, const char *grp=0, bool create=1)
Handle request for localizing a client instance for {usr, grp} from the list.
XrdProofdClient * Client() const
int Post(int type, const char *msg)
Post message on the pipe.
int SendMsgToUser(XrdProofdProtocol *p)
Handle request for sending a message to a user.
XrdProofdProofServ * GetServer(int psid)
Get from the vector server instance with ID psid.
virtual int Config(bool rcf=0)
int Send(void)
Auxilliary Send method.
void Register(const char *dname, XrdProofdDirective *d)
XPClientRequest * Request() const
int DoDirectiveCpCmd(char *, XrdOucStream *, bool)
Process 'cpcmd' directives eg: xpd.cpcmd alien aliencp fmt:"%s %s" put:0.
int SetUserEnvironment(XrdProofdProtocol *p)
Set user environment: set effective user and group ID of the process to the ones of the owner of this...