Logo ROOT   6.16/01
Reference Guide
XrdProofdAux.cxx
Go to the documentation of this file.
1// @(#)root/proofd:$Id$
2// Author: G. Ganis June 2007
3
4/*************************************************************************
5 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12//////////////////////////////////////////////////////////////////////////
13// //
14// XrdProofdAux //
15// //
16// Authors: G. Ganis, CERN, 2007 //
17// //
18// Small auxiliary classes used in XrdProof //
19// //
20//////////////////////////////////////////////////////////////////////////
21#include "XrdProofdPlatform.h"
22
23#include "XrdOuc/XrdOucStream.hh"
24#include "XrdSys/XrdSysPriv.hh"
25
26#include "XpdSysError.h"
27#include "XpdSysLogger.h"
28#include "XrdProofdAux.h"
29#include "XrdProofdConfig.h"
30#include "XrdProofdProtocol.h"
31
32// Tracing
33#include "XrdProofdTrace.h"
34
35#include <grp.h>
36
37// Local definitions
38#ifdef XPD_MAXLEN
39#undefine XPD_MAXLEN
40#endif
41#define XPD_MAXLEN 1024
42
44
45////////////////////////////////////////////////////////////////////////////////
46/// Translates the admin message type in a human readable string.
47/// Must be consistent with the values in XProofProtocol.h
48
50{
51 static const char *msgtypes[] = { "Undef",
52 "QuerySessions", "SessionTag", "SessionAlias", "GetWorkers", "QueryWorkers",
53 "CleanupSessions", "QueryLogPaths", "ReadBuffer", "QueryROOTVersions",
54 "ROOTVersion", "GroupProperties", "SendMsgToUser", "ReleaseWorker",
55 "Exec", "GetFile", "PutFile", "CpFile", "QueryMssUrl"};
56
57 if (type < 1000 || type >= kUndef) {
58 return msgtypes[0];
59 } else {
60 int t = type - 999;
61 return msgtypes[t];
62 }
63}
64
65////////////////////////////////////////////////////////////////////////////////
66/// Translates the proof request type in a human readable string.
67/// Must be consistent with the values in XProofProtocol.h.
68/// The reserved ones are for un
69
71{
72 static const char *reqtypes[] = { "Undef",
73 "XP_login", "XP_auth", "XP_create", "XP_destroy", "XP_attach", "XP_detach",
74 "XP_3107", "XP_3108", "XP_3109", "XP_3110",
75 "XP_urgent", "XP_sendmsg", "XP_admin", "XP_interrupt", "XP_ping",
76 "XP_cleanup", "XP_readbuf", "XP_touch", "XP_ctrlc", "XR_direct" };
77
78 if (type < 3101 || type >= kXP_Undef) {
79 return reqtypes[0];
80 } else {
81 int t = type - 3100;
82 return reqtypes[t];
83 }
84}
85
86////////////////////////////////////////////////////////////////////////////////
87/// Expand path 'p' relative to:
88/// $HOME if begins with ~/
89/// <user>'s $HOME if begins with ~<user>/
90/// $PWD if does not begin with '/' or '~'
91/// getenv(<ENVVAR>) if it begins with $<ENVVAR>)
92/// The returned array of chars is the result of reallocation
93/// of the input one.
94/// If something is inconsistent, for example <ENVVAR> does not
95/// exists, the original string is untouched
96
98{
99 // Make sure there soething to expand
100 if (!p || strlen(p) <= 0 || p[0] == '/')
101 return p;
102
103 char *po = p;
104
105 // Relative to the environment variable
106 if (p[0] == '$') {
107 // Resolve env
108 XrdOucString env(&p[1]);
109 int isl = env.find('/');
110 env.erase(isl);
111 char *p1 = (isl > 0) ? (char *)(p + isl + 2) : 0;
112 if (getenv(env.c_str())) {
113 int lenv = strlen(getenv(env.c_str()));
114 int lp1 = p1 ? strlen(p1) : 0;
115 po = (char *) malloc(lp1 + lenv + 2);
116 if (po) {
117 memcpy(po, getenv(env.c_str()), lenv);
118 if (p1) {
119 memcpy(po+lenv+1, p1, lp1);
120 po[lenv] = '/';
121 }
122 po[lp1 + lenv + 1] = 0;
123 free(p);
124 } else
125 po = p;
126 }
127 return po;
128 }
129
130 // Relative to the local location
131 if (p[0] != '~') {
132 if (getenv("PWD")) {
133 int lpwd = strlen(getenv("PWD"));
134 int lp = strlen(p);
135 po = (char *) malloc(lp + lpwd + 2);
136 if (po) {
137 memcpy(po, getenv("PWD"), lpwd);
138 memcpy(po+lpwd+1, p, lp);
139 po[lpwd] = '/';
140 po[lpwd+lp+1] = 0;
141 free(p);
142 } else
143 po = p;
144 }
145 return po;
146 }
147
148 // Relative to $HOME or <user>'s $HOME
149 if (p[0] == '~') {
150 char *pu = p+1;
151 char *pd = strchr(pu,'/');
152 *pd++ = '\0';
153 // Get the correct user structure
154 XrdProofUI ui;
155 int rc = 0;
156 if (strlen(pu) > 0) {
157 rc = XrdProofdAux::GetUserInfo(pu, ui);
158 } else {
159 rc = XrdProofdAux::GetUserInfo(getuid(), ui);
160 }
161 if (rc == 0) {
162 int ldir = ui.fHomeDir.length();
163 int lpd = strlen(pd);
164 po = (char *) malloc(lpd + ldir + 2);
165 if (po) {
166 memcpy(po, ui.fHomeDir.c_str(), ldir);
167 memcpy(po+ldir+1, pd, lpd);
168 po[ldir] = '/';
169 po[lpd + ldir + 1] = 0;
170 free(p);
171 } else
172 po = p;
173 }
174 return po;
175 }
176
177 // We are done
178 return po;
179}
180
181////////////////////////////////////////////////////////////////////////////////
182/// Expand path 'p' relative to:
183/// $HOME if begins with ~/
184/// <user>'s $HOME if begins with ~<user>/
185/// $PWD if does not begin with '/' or '~'
186/// getenv(<ENVVAR>) if it begins with $<ENVVAR>)
187/// The input string is updated with the result.
188/// If something is inconsistent, for example <ENVVAR> does not
189/// exists, the original string is untouched
190
191void XrdProofdAux::Expand(XrdOucString &p)
192{
193 char *po = strdup((char *)p.c_str());
194 po = Expand(po);
195 p = po;
196 SafeFree(po);
197}
198
199////////////////////////////////////////////////////////////////////////////////
200/// Extract first integer from string at 'str', if any
201
202long int XrdProofdAux::GetLong(char *str)
203{
204 // Reposition on first digit
205 char *p = str;
206 while ((*p < 48 || *p > 57) && (*p) != '\0')
207 p++;
208 if (*p == '\0')
209 return LONG_MAX;
210
211 // Find the last digit
212 int j = 0;
213 while (*(p+j) >= 48 && *(p+j) <= 57)
214 j++;
215 *(p+j) = '\0';
216
217 // Convert now
218 return strtol(p, 0, 10);
219}
220
221////////////////////////////////////////////////////////////////////////////////
222/// Get information about group with 'gid' in a thread safe way.
223/// Retur 0 on success, -errno on error
224
225int XrdProofdAux::GetGroupInfo(const char *grp, XrdProofGI &gi)
226{
227 // Make sure input is defined
228 if (!grp || strlen(grp) <= 0)
229 return -EINVAL;
230
231 // Call getgrgid_r ...
232 struct group gr;
233 struct group *pgr = 0;
234 char buf[2048];
235#if defined(__sun) && !defined(__GNUC__)
236 pgr = getgrnam_r(grp, &gr, buf, sizeof(buf));
237#else
238 getgrnam_r(grp, &gr, buf, sizeof(buf), &pgr);
239#endif
240 if (pgr) {
241 // Fill output
242 gi.fGroup = grp;
243 gi.fGid = (int) gr.gr_gid;
244 // Done
245 return 0;
246 }
247
248 // Failure
249 if (errno != 0)
250 return ((int) -errno);
251 else
252 return -ENOENT;
253}
254
255////////////////////////////////////////////////////////////////////////////////
256/// Get information about group with 'gid' in a thread safe way.
257/// Retur 0 on success, -errno on error
258
260{
261 // Make sure input make sense
262 if (gid <= 0)
263 return -EINVAL;
264
265 // Call getgrgid_r ...
266 struct group gr;
267 struct group *pgr = 0;
268 char buf[2048];
269#if defined(__sun) && !defined(__GNUC__)
270 pgr = getgrgid_r((gid_t)gid, &gr, buf, sizeof(buf));
271#else
272 getgrgid_r((gid_t)gid, &gr, buf, sizeof(buf), &pgr);
273#endif
274 if (pgr) {
275 // Fill output
276 gi.fGroup = gr.gr_name;
277 gi.fGid = gid;
278 // Done
279 return 0;
280 }
281
282 // Failure
283 if (errno != 0)
284 return ((int) -errno);
285 else
286 return -ENOENT;
287}
288
289////////////////////////////////////////////////////////////////////////////////
290/// Get information about user 'usr' in a thread safe way.
291/// Return 0 on success, -errno on error
292
293int XrdProofdAux::GetUserInfo(const char *usr, XrdProofUI &ui)
294{
295 // Make sure input is defined
296 if (!usr || strlen(usr) <= 0)
297 return -EINVAL;
298
299 // Call getpwnam_r ...
300 struct passwd pw;
301 struct passwd *ppw = 0;
302 char buf[2048];
303#if defined(__sun) && !defined(__GNUC__)
304 ppw = getpwnam_r(usr, &pw, buf, sizeof(buf));
305#else
306 getpwnam_r(usr, &pw, buf, sizeof(buf), &ppw);
307#endif
308 if (ppw) {
309 // Fill output
310 ui.fUid = (int) pw.pw_uid;
311 ui.fGid = (int) pw.pw_gid;
312 ui.fHomeDir = pw.pw_dir;
313 ui.fUser = usr;
314 // Done
315 return 0;
316 }
317
318 // Failure
319 if (errno != 0)
320 return ((int) -errno);
321 else
322 return -ENOENT;
323}
324
325////////////////////////////////////////////////////////////////////////////////
326/// Get information about user with 'uid' in a thread safe way.
327/// Retur 0 on success, -errno on error
328
330{
331 // Make sure input make sense
332 if (uid < 0)
333 return -EINVAL;
334
335 // Call getpwuid_r ...
336 struct passwd pw;
337 struct passwd *ppw = 0;
338 char buf[2048];
339#if defined(__sun) && !defined(__GNUC__)
340 ppw = getpwuid_r((uid_t)uid, &pw, buf, sizeof(buf));
341#else
342 getpwuid_r((uid_t)uid, &pw, buf, sizeof(buf), &ppw);
343#endif
344 if (ppw) {
345 // Fill output
346 ui.fUid = uid;
347 ui.fGid = (int) pw.pw_gid;
348 ui.fHomeDir = pw.pw_dir;
349 ui.fUser = pw.pw_name;
350 // Done
351 return 0;
352 }
353
354 // Failure
355 if (errno != 0)
356 return ((int) -errno);
357 else
358 return -ENOENT;
359}
360
361////////////////////////////////////////////////////////////////////////////////
362/// Write nb bytes at buf to descriptor 'fd' ignoring interrupts
363/// Return the number of bytes written or -1 in case of error
364
365int XrdProofdAux::Write(int fd, const void *buf, size_t nb)
366{
367 if (fd < 0)
368 return -1;
369
370 const char *pw = (const char *)buf;
371 int lw = nb;
372 int nw = 0, written = 0;
373 while (lw) {
374 if ((nw = write(fd, pw + written, lw)) < 0) {
375 if (errno == EINTR) {
376 errno = 0;
377 continue;
378 } else {
379 break;
380 }
381 }
382 // Count
383 written += nw;
384 lw -= nw;
385 }
386
387 // Done
388 return written;
389}
390
391////////////////////////////////////////////////////////////////////////////////
392/// Logs error message 'emsg' to file 'flog' using standard technology
393
394void XrdProofdAux::LogEmsgToFile(const char *flog, const char *emsg, const char *pfx)
395{
396 XPDLOC(AUX, "Aux::LogEmsgToFile")
397
398 if (flog && strlen(flog)) {
399 // Open the file in write-only, append mode
400 int logfd = open(flog, O_WRONLY|O_APPEND, 0644);
401 if (logfd >= 0) {
402 fcntl(logfd, F_SETFD, FD_CLOEXEC);
403 // Attach a logger to the file
404 XrdSysLogger logger(logfd, 0);
405 XrdSysError error(&logger, "xpd");
406 // Log the message
407 if (emsg && strlen(emsg) > 0) error.Emsg("-E", pfx, emsg);
408 // Make sure that it is written to file
409 if (fsync(logfd) != 0)
410 TRACE(XERR, "problem syncing file "<<flog<<" - errno: "<<errno);
411 // Free the descriptor
412 if (close(logfd) != 0)
413 TRACE(XERR, "problem closing file "<<flog<<" - errno: "<<errno);
414 } else {
415 TRACE(XERR, "file "<<flog<<" could not be opened - errno: "<<errno);
416 }
417 } else {
418 TRACE(XERR, "file path undefined!");
419 }
420 // Done
421 return;
422}
423
424////////////////////////////////////////////////////////////////////////////////
425/// Make sure that 'path' exists and is owned by the entity
426/// described by 'ui'.
427/// If changeown is TRUE it tries to acquire the privileges before.
428/// Return 0 in case of success, -1 in case of error
429
430int XrdProofdAux::AssertDir(const char *path, XrdProofUI ui, bool changeown)
431{
432 XPDLOC(AUX, "Aux::AssertDir")
433
434 TRACE(DBG, path);
435
436 if (!path || strlen(path) <= 0)
437 return -1;
438 XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
439 if (XpdBadPGuard(pGuard, ui.fUid) && changeown) {
440 TRACE(XERR, "could not get privileges to change ownership");
441 return -1;
442 }
443
444 if (mkdir(path, 0755) != 0 && (errno != EEXIST)) {
445 TRACE(XERR, "unable to create dir: "<<path<<" (errno: "<<errno<<")");
446 return -1;
447 }
448
449 if (changeown) {
450 // Set ownership of the path to the client
451 if (chown(path, ui.fUid, ui.fGid) == -1) {
452 TRACE(XERR, "cannot set user ownership on path (errno: "<<errno<<")");
453 return -1;
454 }
455 }
456
457 // We are done
458 return 0;
459}
460
461////////////////////////////////////////////////////////////////////////////////
462/// Make sure that the base dir of 'path' is either owned by 'ui' or
463/// gives full permissions to 'ui'.
464/// If 'path' is a directory, go through the paths inside it recursively.
465/// Return 0 in case of success, -1 in case of error
466
468{
469 XPDLOC(AUX, "Aux::AssertBaseDir")
470
471 TRACE(DBG, path);
472
473 if (!path || strlen(path) <= 0)
474 return -1;
475
476 XrdOucString base(path);
477 if (base.endswith("/")) base.erasefromend(1);
478 int isl = base.rfind('/');
479 if (isl != 0) base.erase(isl);
480 TRACE(DBG, "base: " <<base);
481
482 struct stat st;
483 if (stat(base.c_str(), &st) != 0) {
484 // Failure: stop
485 TRACE(XERR, "unable to stat base path: "<<base<<" (errno: "<<errno<<")");
486 return -1;
487 }
488
489 // Check ownership and permissions
490 if (ui.fUid != (int) st.st_uid) {
491 unsigned pa = (st.st_mode & S_IRWXG);
492 if (ui.fGid != (int) st.st_gid)
493 pa |= (st.st_mode & S_IRWXO);
494 else
495 pa |= S_IRWXO;
496 if (pa != 0077) {
497 TRACE(XERR, "effective user has not full permissions on base path: "<<base);
498 return -1;
499 }
500 }
501
502 // Done
503 return 0;
504}
505
506////////////////////////////////////////////////////////////////////////////////
507/// Change the ownership of 'path' to the entity described by 'ui'.
508/// If 'path' is a directory, go through the paths inside it recursively.
509/// Return 0 in case of success, -1 in case of error
510
511int XrdProofdAux::ChangeOwn(const char *path, XrdProofUI ui)
512{
513 XPDLOC(AUX, "Aux::ChangeOwn")
514
515 TRACE(DBG, path);
516
517 if (!path || strlen(path) <= 0)
518 return -1;
519 DIR *dir = opendir(path);
520 if (dir) {
521 // Loop over the dir
522 XrdOucString proot(path);
523 if (!proot.endswith('/')) proot += "/";
524
525 struct dirent *ent = 0;
526 while ((ent = readdir(dir))) {
527 if (ent->d_name[0] == '.' || !strcmp(ent->d_name, "..")) continue;
528 XrdOucString fn(proot);
529 fn += ent->d_name;
530
531 // Apply recursively
532 if (XrdProofdAux::ChangeOwn(fn.c_str(), ui) != 0) {
533 TRACE(XERR, "problems changing recursively ownership of: "<<fn);
534 closedir(dir);
535 return -1;
536 }
537 }
538 // Close the directory
539 closedir(dir);
540
541 } else {
542 // If it was a directory and opening failed, we fail
543 if (errno != 0 && (errno != ENOTDIR)) {
544 TRACE(XERR,"cannot open "<<path<< "- errno: "<< errno);
545 return -1;
546 }
547 // Get the privileges, if needed
548 XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
549 if (XpdBadPGuard(pGuard, ui.fUid)) {
550 TRACE(XERR, "could not get privileges to change ownership");
551 return -1;
552 }
553 // Set ownership of the path to the client
554 if (chown(path, ui.fUid, ui.fGid) == -1) {
555 TRACE(XERR, "cannot set user ownership on path (errno: "<<errno<<")");
556 return -1;
557 }
558 }
559 // We are done
560 return 0;
561}
562
563////////////////////////////////////////////////////////////////////////////////
564/// Change the permission mode of 'path' to 'mode'.
565/// If 'path' is a directory, go through the paths inside it recursively.
566/// Return 0 in case of success, -1 in case of error
567
568int XrdProofdAux::ChangeMod(const char *path, unsigned int mode)
569{
570 XPDLOC(AUX, "Aux::ChangeMod")
571
572 TRACE(HDBG, "path: "<<path);
573
574 if (!path || strlen(path) <= 0)
575 return -1;
576
577 struct stat st;
578 if (stat(path,&st) != 0) {
579 // Failure: stop
580 TRACE(XERR, "unable to stat path: "<<path<<" (errno: "<<errno<<")");
581 return -1;
582 }
583
584 // Change the path first; then do it recursively, if needed
585 { // Get the privileges, if needed
586 XrdSysPrivGuard pGuard(st.st_uid, st.st_gid);
587 if (XpdBadPGuard(pGuard, st.st_uid)) {
588 TRACE(XERR, "could not get privileges to change ownership");
589 return -1;
590 }
591 // Set ownership of the path to the client
592 if (chmod(path, mode) == -1) {
593 TRACE(XERR, "cannot change permissions on path (errno: "<<errno<<")");
594 return -1;
595 }
596 }
597
598 // If is a directory apply this on it
599 if (S_ISDIR(st.st_mode)) {
600 // Loop over the dir
601 DIR *dir = opendir(path);
602 if (!dir) {
603 TRACE(XERR,"cannot open "<<path<< "- errno: "<< errno);
604 return -1;
605 }
606 XrdOucString proot(path);
607 if (!proot.endswith('/')) proot += "/";
608
609 struct dirent *ent = 0;
610 while ((ent = readdir(dir))) {
611 if (ent->d_name[0] == '.' || !strcmp(ent->d_name, "..")) continue;
612 XrdOucString fn(proot);
613 fn += ent->d_name;
614
615 struct stat xst;
616 if (stat(fn.c_str(),&xst) == 0) {
617 { // Get the privileges, if needed
618 TRACE(HDBG,"getting {"<<xst.st_uid<<", "<< xst.st_gid<<"} identity");
619 XrdSysPrivGuard pGuard(xst.st_uid, xst.st_gid);
620 if (XpdBadPGuard(pGuard, xst.st_uid)) {
621 TRACE(XERR, "could not get privileges to change ownership");
622 closedir(dir);
623 return -1;
624 }
625 // Set the permission mode of the path
626 if (chmod(fn.c_str(), mode) == -1) {
627 TRACE(XERR, "cannot change permissions on path (errno: "<<errno<<")");
628 closedir(dir);
629 return -1;
630 }
631 }
632 // If is a directory apply this on it
633 if (S_ISDIR(xst.st_mode)) {
634 if (XrdProofdAux::ChangeMod(fn.c_str(), mode) != 0) {
635 TRACE(XERR, "problems changing recursively permissions of: "<<fn);
636 closedir(dir);
637 return -1;
638 }
639 }
640 } else {
641 TRACE(XERR, "unable to stat dir: "<<fn<<" (errno: "<<errno<<")");
642 }
643 }
644 // Close the directory
645 closedir(dir);
646 }
647
648 // We are done
649 return 0;
650}
651
652////////////////////////////////////////////////////////////////////////////////
653/// Change current directory to 'dir'.
654/// If changeown is TRUE it tries to acquire the privileges before.
655/// Return 0 in case of success, -1 in case of error
656
657int XrdProofdAux::ChangeToDir(const char *dir, XrdProofUI ui, bool changeown)
658{
659 XPDLOC(AUX, "Aux::ChangeToDir")
660
661 TRACE(DBG, "changing to " << ((dir) ? dir : "**undef***"));
662
663 if (!dir || strlen(dir) <= 0)
664 return -1;
665
666 if (changeown && ((int) geteuid() != ui.fUid || (int) getegid() != ui.fGid)) {
667
668 XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
669 if (XpdBadPGuard(pGuard, ui.fUid)) {
670 TRACE(XERR, changeown << ": could not get privileges; {uid,gid} req: {"<< ui.fUid <<","<<ui.fGid<<
671 "}, {euid,egid}: {" << geteuid() <<","<<getegid()<<"}, {uid,gid}: {"<<getuid()<<","<<getgid() << "}; errno: "<<errno);
672 return -1;
673 }
674 if (chdir(dir) == -1) {
675 TRACE(XERR, changeown << ": can't change directory to '"<< dir<<"'; {ui.fUid,ui.fGid}: {"<< ui.fUid <<","<<ui.fGid<<
676 "}, {euid,egid}: {" << geteuid() <<","<<getegid()<<"}, {uid,gid}: {"<<getuid()<<","<<getgid() << "}; errno: "<<errno);
677 return -1;
678 }
679 } else {
680 if (chdir(dir) == -1) {
681 TRACE(XERR, changeown << ": can't change directory to "<< dir <<
682 ", euid: " << geteuid() <<", uid:"<<getuid()<<"; errno: "<<errno);
683 return -1;
684 }
685 }
686
687 // We are done
688 return 0;
689}
690
691////////////////////////////////////////////////////////////////////////////////
692/// Create a symlink 'link' to 'path'
693/// Return 0 in case of success, -1 in case of error
694
695int XrdProofdAux::SymLink(const char *path, const char *link)
696{
697 XPDLOC(AUX, "Aux::SymLink")
698
699 TRACE(DBG, path<<" -> "<<link);
700
701 if (!path || strlen(path) <= 0 || !link || strlen(link) <= 0)
702 return -1;
703
704 // Remove existing link, if any
705 if (unlink(link) != 0 && errno != ENOENT) {
706 TRACE(XERR, "problems unlinking existing symlink "<< link<<
707 " (errno: "<<errno<<")");
708 return -1;
709 }
710 if (symlink(path, link) != 0) {
711 TRACE(XERR, "problems creating symlink " << link<<
712 " (errno: "<<errno<<")");
713 return -1;
714 }
715
716 // We are done
717 return 0;
718}
719
720////////////////////////////////////////////////////////////////////////////////
721/// Check existence and match condition of an 'if' directive
722/// If none (valid) is found, return -1.
723/// Else, return number of chars matching.
724
725int XrdProofdAux::CheckIf(XrdOucStream *s, const char *host)
726{
727 XPDLOC(AUX, "")
728
729 // There must be an 'if'
730 char *val = s ? s->GetWord() : 0;
731 if (!val || strncmp(val,"if",2)) {
732 if (val)
733 // allow the analysis of the token
734 s->RetToken();
735 return -1;
736 }
737
738 // check value if any
739 val = s->GetWord();
740 if (!val)
741 return -1;
742
743 // Deprecate
744 TRACE(ALL, ">>> Warning: 'if' conditions at the end of the directive are deprecated ");
745 TRACE(ALL, ">>> Please use standard Scalla/Xrootd 'if-else-fi' constructs");
746 TRACE(ALL, ">>> (see http://xrootd.slac.stanford.edu/doc/xrd_config/xrd_config.htm)");
747
748 // Notify
749 TRACE(DBG, "Aux::CheckIf: <pattern>: " <<val);
750
751 // Return number of chars matching
752 XrdOucString h(host);
753 return h.matches((const char *)val);
754}
755
756////////////////////////////////////////////////////////////////////////////////
757/// Find out and return the number of CPUs in the local machine.
758/// Return -1 in case of failure.
759
761{
762 XPDLOC(AUX, "Aux::GetNumCPUs")
763
764 static int ncpu = -1;
765
766 // Use cached value, if any
767 if (ncpu > 0)
768 return ncpu;
769 ncpu = 0;
770
771 XrdOucString emsg;
772
773#if defined(linux)
774 // Look for in the /proc/cpuinfo file
775 XrdOucString fcpu("/proc/cpuinfo");
776 FILE *fc = fopen(fcpu.c_str(), "r");
777 if (!fc) {
778 if (errno == ENOENT) {
779 TRACE(XERR, "/proc/cpuinfo missing!!! Something very bad going on");
780 } else {
781 XPDFORM(emsg, "cannot open %s; errno: %d", fcpu.c_str(), errno);
782 TRACE(XERR, emsg);
783 }
784 return -1;
785 }
786 // Read lines and count those starting with "processor"
787 char line[2048] = { 0 };
788 while (fgets(line, sizeof(line), fc)) {
789 if (!strncmp(line, "processor", strlen("processor")))
790 ncpu++;
791 }
792 // Close the file
793 fclose(fc);
794
795#elif defined(__sun)
796
797 // Run "psrinfo" in popen and count lines
798 FILE *fp = popen("psrinfo", "r");
799 if (fp != 0) {
800 char line[2048] = { 0 };
801 while (fgets(line, sizeof(line), fp))
802 ncpu++;
803 pclose(fp);
804 }
805
806#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
807
808 // Run "sysctl -n hw.ncpu" in popen and decode the output
809 FILE *fp = popen("sysctl -n hw.ncpu", "r");
810 if (fp != 0) {
811 char line[2048] = { 0 };
812 while (fgets(line, sizeof(line), fp))
813 ncpu = XrdProofdAux::GetLong(&line[0]);
814 pclose(fp);
815 }
816#endif
817
818 TRACE(DBG, "# of cores found: "<<ncpu);
819
820 // Done
821 return (ncpu <= 0) ? (int)(-1) : ncpu ;
822}
823
824#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
825////////////////////////////////////////////////////////////////////////////////
826/// Returns a list of all processes on the system. This routine
827/// allocates the list and puts it in *plist and counts the
828/// number of entries in 'nproc'. Caller is responsible for 'freeing'
829/// the list.
830/// On success, the function returns 0.
831/// On error, the function returns an errno value.
832///
833/// Adapted from: reply to Technical Q&A 1123,
834/// http://developer.apple.com/qa/qa2001/qa1123.html
835///
836
837int XrdProofdAux::GetMacProcList(kinfo_proc **plist, int &nproc)
838{
839 XPDLOC(AUX, "Aux::GetMacProcList")
840
841 int rc = 0;
842 kinfo_proc *res;
843 bool done = 0;
844 static const int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
845
846 TRACE(DBG, "enter");
847
848 // Declaring name as const requires us to cast it when passing it to
849 // sysctl because the prototype doesn't include the const modifier.
850 size_t len = 0;
851
852 if (!plist || (*plist))
853 return EINVAL;
854 nproc = 0;
855
856 // We start by calling sysctl with res == 0 and len == 0.
857 // That will succeed, and set len to the appropriate length.
858 // We then allocate a buffer of that size and call sysctl again
859 // with that buffer. If that succeeds, we're done. If that fails
860 // with ENOMEM, we have to throw away our buffer and loop. Note
861 // that the loop causes use to call sysctl with 0 again; this
862 // is necessary because the ENOMEM failure case sets length to
863 // the amount of data returned, not the amount of data that
864 // could have been returned.
865
866 res = 0;
867 do {
868 // Call sysctl with a 0 buffer.
869 len = 0;
870 if ((rc = sysctl((int *)name, (sizeof(name)/sizeof(*name)) - 1,
871 0, &len, 0, 0)) == -1) {
872 rc = errno;
873 }
874
875 // Allocate an appropriately sized buffer based on the results
876 // from the previous call.
877 if (rc == 0) {
878 res = (kinfo_proc *) malloc(len);
879 if (!res)
880 rc = ENOMEM;
881 }
882
883 // Call sysctl again with the new buffer. If we get an ENOMEM
884 // error, toss away our buffer and start again.
885 if (rc == 0) {
886 if ((rc = sysctl((int *)name, (sizeof(name)/sizeof(*name)) - 1,
887 res, &len, 0, 0)) == -1) {
888 rc = errno;
889 }
890 if (rc == 0) {
891 done = 1;
892 } else if (rc == ENOMEM) {
893 if (res)
894 free(res);
895 res = 0;
896 rc = 0;
897 }
898 }
899 } while (rc == 0 && !done);
900
901 // Clean up and establish post conditions.
902 if (rc != 0 && !res) {
903 free(res);
904 res = 0;
905 }
906 *plist = res;
907 if (rc == 0)
908 nproc = len / sizeof(kinfo_proc);
909
910 // Done
911 return rc;
912}
913#endif
914
915////////////////////////////////////////////////////////////////////////////////
916/// Get from the process table list of PIDs for processes named "proofserv'
917/// For {linux, sun, macosx} it uses the system info; for other systems it
918/// invokes the command shell 'ps ax' via popen.
919/// Return the number of processes found, or -1 if some error occured.
920
921int XrdProofdAux::GetProcesses(const char *pn, std::map<int,XrdOucString> *pmap)
922{
923 XPDLOC(AUX, "Aux::GetProcesses")
924
925 int np = 0;
926
927 // Check input consistency
928 if (!pn || strlen(pn) <= 0 || !pmap) {
929 TRACE(XERR, "invalid inputs");
930 return -1;
931 }
932 TRACE(DBG, "process name: "<<pn);
933
934 XrdOucString emsg;
935
936#if defined(linux) || defined(__sun)
937 // Loop over the "/proc" dir
938 DIR *dir = opendir("/proc");
939 if (!dir) {
940 emsg = "cannot open /proc - errno: ";
941 emsg += errno;
942 TRACE(DBG, emsg.c_str());
943 return -1;
944 }
945
946 struct dirent *ent = 0;
947 while ((ent = readdir(dir))) {
948 if (DIGIT(ent->d_name[0])) {
949 XrdOucString fn("/proc/", 256);
950 fn += ent->d_name;
951#if defined(linux)
952 fn += "/status";
953 // Open file
954 FILE *ffn = fopen(fn.c_str(), "r");
955 if (!ffn) {
956 emsg = "cannot open file ";
957 emsg += fn; emsg += " - errno: "; emsg += errno;
958 TRACE(HDBG, emsg);
959 continue;
960 }
961 // Read info
962 bool ok = 0;
963 int pid = -1;
964 char line[2048] = { 0 };
965 while (fgets(line, sizeof(line), ffn)) {
966 // Check name
967 if (strstr(line, "Name:")) {
968 if (strstr(line, pn)) {
969 // Good one
970 ok = 1;
971 }
972 // We are done with this proc file
973 break;
974 }
975 }
976 if (ok) {
977 fclose(ffn);
978 fn.replace("/status", "/cmdline");
979 // Open file
980 if (!(ffn = fopen(fn.c_str(), "r"))) {
981 emsg = "cannot open file ";
982 emsg += fn; emsg += " - errno: "; emsg += errno;
983 TRACE(HDBG, emsg);
984 continue;
985 }
986 // Read the command line
987 XrdOucString cmd;
988 char buf[256];
989 char *p = &buf[0];
990 int pos = 0, ltot = 0, nr = 1;
991 errno = 0;
992 while (nr > 0) {
993 while ((nr = read(fileno(ffn), p + pos, 1)) == -1 && errno == EINTR) {
994 errno = 0;
995 }
996 ltot += nr;
997 if (ltot == 254) {
998 buf[255] = 0;
999 cmd += buf;
1000 pos = 0;
1001 ltot = 0;
1002 } else if (nr > 0) {
1003 if (*p == 0) *p = ' ';
1004 p += nr;
1005 }
1006 }
1007 // Null terminate
1008 buf[ltot] = 0;
1009 cmd += buf;
1010 // Good one: take the pid
1011 pid = strtol(ent->d_name, 0, 10);
1012 pmap->insert(std::make_pair(pid, cmd));
1013 np++;
1014 }
1015 // Close the file
1016 fclose(ffn);
1017#elif defined(__sun)
1018 fn += "/psinfo";
1019 // Open file
1020 int ffd = open(fn.c_str(), O_RDONLY);
1021 if (ffd <= 0) {
1022 emsg = "cannot open file ";
1023 emsg += fn; emsg += " - errno: "; emsg += errno;
1024 TRACE(HDBG, emsg);
1025 continue;
1026 }
1027 // Get the information
1028 psinfo_t psi;
1029 if (read(ffd, &psi, sizeof(psinfo_t)) != sizeof(psinfo_t)) {
1030 emsg = "cannot read ";
1031 emsg += fn; emsg += ": errno: "; emsg += errno;
1032 TRACE(XERR, emsg);
1033 close(ffd);
1034 continue;
1035 }
1036 // Check name
1037 if (strstr(psi.pr_fname, pn)) {
1038 // Build command line
1039 XrdOucString cmd(psi.pr_fname);
1040 if (cmd.length() > 0) cmd += " ";
1041 cmd += psi.pr_psargs;
1042 // Good one: take the pid
1043 int pid = strtol(ent->d_name, 0, 10);
1044 pmap->insert(std::make_pair(pid, cmd));
1045 np++;
1046 }
1047 // Close the file
1048 close(ffd);
1049#endif
1050 }
1051 }
1052 // Close the directory
1053 closedir(dir);
1054
1055#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
1056
1057 // Get the proclist
1058 kinfo_proc *pl = 0;
1059 int ern = 0;
1060 if ((ern = XrdProofdAux::GetMacProcList(&pl, np)) != 0) {
1061 emsg = "cannot get the process list: errno: ";
1062 emsg += ern;
1063 TRACE(XERR, emsg);
1064 return -1;
1065 }
1066
1067 // Loop over the list
1068 int ii = np;
1069 while (ii--) {
1070 if (strstr(pl[ii].kp_proc.p_comm, pn)) {
1071 // Good one: take the pid
1072 pmap->insert(std::make_pair(pl[ii].kp_proc.p_pid, XrdOucString(pl[ii].kp_proc.p_comm)));
1073 np++;
1074 }
1075 }
1076 // Cleanup
1077 free(pl);
1078#else
1079
1080 // For the remaining cases we use 'ps' via popen to localize the processes
1081
1082 // Build command
1083 XrdOucString cmd = "ps ax -ww | grep proofserv 2>/dev/null";
1084
1085 // Run it ...
1086 XrdOucString pids = ":";
1087 FILE *fp = popen(cmd.c_str(), "r");
1088 if (fp != 0) {
1089 char line[2048] = { 0 };
1090 while (fgets(line, sizeof(line), fp)) {
1091 int pid = (int) XrdProofdAux::GetLong(&line[0]);
1092 pmap->insert(std::make_pair(pid, XrdOucString(line)));
1093 np++;
1094 }
1095 pclose(fp);
1096 } else {
1097 // Error executing the command
1098 return -1;
1099 }
1100
1101#endif
1102
1103 // Done
1104 return np;
1105}
1106
1107////////////////////////////////////////////////////////////////////////////////
1108/// Extract an integer from a file
1109
1110int XrdProofdAux::GetIDFromPath(const char *path, XrdOucString &emsg)
1111{
1112 emsg = "";
1113 // Get the ID
1114 int id = -1;
1115 FILE *fid = fopen(path, "r");
1116 if (fid) {
1117 char line[64];
1118 if (fgets(line, sizeof(line), fid)) {
1119 if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0;
1120 id = atoi(line);
1121 }
1122 fclose(fid);
1123 } else if (errno != ENOENT) {
1124 XPDFORM(emsg, "GetIDFromPath: error reading id from: %s (errno: %d)",
1125 path, errno);
1126 }
1127 // Done
1128 return id;
1129}
1130
1131////////////////////////////////////////////////////////////////////////////////
1132/// Returns true is 's' contains at least one of the comma-separated tokens
1133/// in 'tokens'. Else returns false.
1134
1135bool XrdProofdAux::HasToken(const char *s, const char *tokens)
1136{
1137 if (s && strlen(s) > 0) {
1138 XrdOucString tks(tokens), tok;
1139 int from = 0;
1140 while ((from = tks.tokenize(tok, from, ',')) != -1)
1141 if (strstr(s, tok.c_str())) return 1;
1142 }
1143 return 0;
1144}
1145
1146////////////////////////////////////////////////////////////////////////////////
1147/// Check if a process named 'pname' and process 'pid' is still
1148/// in the process table.
1149/// For {linux, sun, macosx} it uses the system info; for other systems it
1150/// invokes the command shell 'ps ax' via popen.
1151/// Return 1 if running, 0 if not running, -1 if the check could not be run.
1152
1153int XrdProofdAux::VerifyProcessByID(int pid, const char *pname)
1154{
1155 XPDLOC(AUX, "Aux::VerifyProcessByID")
1156
1157 int rc = 0;
1158
1159 TRACE(DBG, "pid: "<<pid);
1160
1161 // Check input consistency
1162 if (pid < 0) {
1163 TRACE(XERR, "invalid pid");
1164 return -1;
1165 }
1166
1167 XrdOucString emsg;
1168
1169 // Name
1170 const char *pn = (pname && strlen(pname) > 0) ? pname : "proofserv";
1171
1172#if defined(linux)
1173 // Look for the relevant /proc dir
1174 XrdOucString fn("/proc/");
1175 fn += pid;
1176 fn += "/stat";
1177 FILE *ffn = fopen(fn.c_str(), "r");
1178 if (!ffn) {
1179 if (errno == ENOENT) {
1180 TRACE(DBG, "process does not exists anymore");
1181 return 0;
1182 } else {
1183 XPDFORM(emsg, "cannot open %s; errno: %d", fn.c_str(), errno);
1184 TRACE(XERR, emsg);
1185 return -1;
1186 }
1187 }
1188 // Read status line
1189 char line[2048] = { 0 };
1190 if (fgets(line, sizeof(line), ffn)) {
1192 // Still there
1193 rc = 1;
1194 } else {
1195 XPDFORM(emsg, "cannot read %s; errno: %d", fn.c_str(), errno);
1196 TRACE(XERR, emsg);
1197 fclose(ffn);
1198 return -1;
1199 }
1200 // Close the file
1201 fclose(ffn);
1202
1203#elif defined(__sun)
1204
1205 // Look for the relevant /proc dir
1206 XrdOucString fn("/proc/");
1207 fn += pid;
1208 fn += "/psinfo";
1209 int ffd = open(fn.c_str(), O_RDONLY);
1210 if (ffd <= 0) {
1211 if (errno == ENOENT) {
1212 TRACE(DBG, "VerifyProcessByID: process does not exists anymore");
1213 return 0;
1214 } else {
1215 XPDFORM(emsg, "cannot open %s; errno: %d", fn.c_str(), errno);
1216 TRACE(XERR, emsg);
1217 close(ffd);
1218 return -1;
1219 }
1220 }
1221 // Get the information
1222 psinfo_t psi;
1223 if (read(ffd, &psi, sizeof(psinfo_t)) != sizeof(psinfo_t)) {
1224 XPDFORM(emsg, "cannot read %s; errno: %d", fn.c_str(), errno);
1225 TRACE(XERR, emsg);
1226 close(ffd);
1227 return -1;
1228 }
1229
1230 // Verify now
1231 if (XrdProofdAux::HasToken(psi.pr_fname, pn))
1232 // The process is still there
1233 rc = 1;
1234
1235 // Close the file
1236 close(ffd);
1237
1238#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
1239
1240 // Get the proclist
1241 kinfo_proc *pl = 0;
1242 int np;
1243 int ern = 0;
1244 if ((ern = XrdProofdAux::GetMacProcList(&pl, np)) != 0) {
1245 XPDFORM(emsg, "cannot get the process list: errno: %d", ern);
1246 TRACE(XERR, emsg);
1247 return -1;
1248 }
1249
1250 // Loop over the list
1251 while (np--) {
1252 if (pl[np].kp_proc.p_pid == pid &&
1253 XrdProofdAux::HasToken(pl[np].kp_proc.p_comm, pn)) {
1254 // Process still exists
1255 rc = 1;
1256 break;
1257 }
1258 }
1259 // Cleanup
1260 free(pl);
1261#else
1262 // Use the output of 'ps ax' as a backup solution
1263 XrdOucString cmd = "ps ax | grep proofserv 2>/dev/null";
1264 if (pname && strlen(pname))
1265 cmd.replace("proofserv", pname);
1266 FILE *fp = popen(cmd.c_str(), "r");
1267 if (fp != 0) {
1268 char line[2048] = { 0 };
1269 while (fgets(line, sizeof(line), fp)) {
1270 if (pid == XrdProofdAux::GetLong(line)) {
1271 // Process still running
1272 rc = 1;
1273 break;
1274 }
1275 }
1276 pclose(fp);
1277 } else {
1278 // Error executing the command
1279 return -1;
1280 }
1281#endif
1282 // Done
1283 return rc;
1284}
1285
1286////////////////////////////////////////////////////////////////////////////////
1287/// Kill the process 'pid'.
1288/// A SIGTERM is sent, unless 'kill' is TRUE, in which case a SIGKILL is used.
1289/// If add is TRUE (default) the pid is added to the list of processes
1290/// requested to terminate.
1291/// Return 0 on success, -1 if not allowed or other errors occured.
1292
1293int XrdProofdAux::KillProcess(int pid, bool forcekill, XrdProofUI ui, bool changeown)
1294{
1295 XPDLOC(AUX, "Aux::KillProcess")
1296
1297 TRACE(DBG, "pid: "<<pid<< ", forcekill: "<< forcekill);
1298
1299 XrdOucString msg;
1300 if (pid > 0) {
1301 // We need the right privileges to do this
1302 XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
1303 if (XpdBadPGuard(pGuard, ui.fUid) && changeown) {
1304 TRACE(XERR, "could not get privileges");
1305 return -1;
1306 } else {
1307 bool signalled = 1;
1308 if (forcekill) {
1309 // Hard shutdown via SIGKILL
1310 if (kill(pid, SIGKILL) != 0) {
1311 if (errno != ESRCH) {
1312 XPDFORM(msg, "kill(pid,SIGKILL) failed for process %d; errno: %d", pid, errno);
1313 TRACE(XERR, msg);
1314 return -1;
1315 }
1316 signalled = 0;
1317 }
1318 } else {
1319 // Softer shutdown via SIGTERM
1320 if (kill(pid, SIGTERM) != 0) {
1321 if (errno != ESRCH) {
1322 XPDFORM(msg, "kill(pid,SIGTERM) failed for process %d; errno: %d", pid, errno);
1323 TRACE(XERR, msg);
1324 return -1;
1325 }
1326 signalled = 0;
1327 }
1328 }
1329 // Notify failure
1330 if (!signalled) {
1331 TRACE(DBG, "process ID "<<pid<<" not found in the process table");
1332 }
1333 }
1334 } else {
1335 return -1;
1336 }
1337
1338 // Done
1339 return 0;
1340}
1341
1342////////////////////////////////////////////////////////////////////////////////
1343/// Remove directory at path and its content.
1344/// Returns 0 on success, -errno of the last error on failure
1345
1346int XrdProofdAux::RmDir(const char *path)
1347{
1348 XPDLOC(AUX, "Aux::RmDir")
1349
1350 int rc = 0;
1351
1352 TRACE(DBG, path);
1353
1354 // Open dir
1355 DIR *dir = opendir(path);
1356 if (!dir) {
1357 TRACE(XERR, "cannot open dir "<<path<<" ; error: "<<errno);
1358 return -errno;
1359 }
1360
1361 // Scan the directory
1362 XrdOucString entry;
1363 struct stat st;
1364 struct dirent *ent = 0;
1365 while ((ent = (struct dirent *)readdir(dir))) {
1366 // Skip the basic entries
1367 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue;
1368 // Get info about the entry
1369 XPDFORM(entry, "%s/%s", path, ent->d_name);
1370 if (stat(entry.c_str(), &st) != 0) {
1371 TRACE(XERR, "cannot stat entry "<<entry<<" ; error: "<<errno);
1372 rc = -errno;
1373 break;
1374 }
1375 // Remove directories recursively
1376 if (S_ISDIR(st.st_mode)) {
1377 rc = XrdProofdAux::RmDir(entry.c_str());
1378 if (rc != 0) {
1379 TRACE(XERR, "problems removing"<<entry<<" ; error: "<<-rc);
1380 break;
1381 }
1382 } else {
1383 // Remove the entry
1384 if (unlink(entry.c_str()) != 0) {
1385 rc = -errno;
1386 TRACE(XERR, "problems removing"<<entry<<" ; error: "<<-rc);
1387 break;
1388 }
1389 }
1390 }
1391 // Close the directory
1392 closedir(dir);
1393
1394 // If successful, remove the directory
1395 if (!rc && rmdir(path) != 0) {
1396 rc = -errno;
1397 TRACE(XERR, "problems removing"<<path<<" ; error: "<<-rc);
1398 }
1399
1400 // Done
1401 return rc;
1402}
1403
1404////////////////////////////////////////////////////////////////////////////////
1405/// Move content of directory at oldpath to newpath.
1406/// The destination path 'newpath' must exist.
1407/// Returns 0 on success, -errno of the last error on failure
1408
1409int XrdProofdAux::MvDir(const char *oldpath, const char *newpath)
1410{
1411 XPDLOC(AUX, "Aux::MvDir")
1412
1413 int rc = 0;
1414
1415 TRACE(DBG, "oldpath "<<oldpath<<", newpath: "<<newpath);
1416
1417 // Open existing dir
1418 DIR *dir = opendir(oldpath);
1419 if (!dir) {
1420 TRACE(XERR, "cannot open dir "<<oldpath<<" ; error: "<<errno);
1421 return -errno;
1422 }
1423
1424 // Assert destination dir
1425 struct stat st;
1426 if (stat(newpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
1427 TRACE(XERR, "destination dir "<<newpath<<
1428 " does not exist or is not a directory; errno: "<<errno);
1429 closedir(dir);
1430 return -ENOENT;
1431 }
1432
1433 // Scan the source directory
1434 XrdOucString srcentry, dstentry;
1435 struct dirent *ent = 0;
1436 while ((ent = (struct dirent *)readdir(dir))) {
1437 // Skip the basic entries
1438 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue;
1439 // Get info about the entry
1440 XPDFORM(srcentry, "%s/%s", oldpath, ent->d_name);
1441 if (stat(srcentry.c_str(), &st) != 0) {
1442 TRACE(XERR, "cannot stat entry "<<srcentry<<" ; error: "<<errno);
1443 rc = -errno;
1444 break;
1445 }
1446 // Destination entry
1447 XPDFORM(dstentry, "%s/%s", newpath, ent->d_name);
1448 // Mv directories recursively
1449 if (S_ISDIR(st.st_mode)) {
1450 mode_t srcmode = st.st_mode;
1451 // Create dest sub-dir
1452 if (mkdir(dstentry.c_str(), srcmode) != 0 && (errno != EEXIST)) {
1453 TRACE(XERR, "cannot create entry "<<dstentry<<" ; error: "<<errno);
1454 rc = -errno;
1455 break;
1456 }
1457 if ((rc = XrdProofdAux::MvDir(srcentry.c_str(), dstentry.c_str())) != 0) {
1458 TRACE(XERR, "problems moving "<<srcentry<<" to "<<dstentry<<"; error: "<<-rc);
1459 break;
1460 }
1461 if ((rc = XrdProofdAux::RmDir(srcentry.c_str())) != 0) {
1462 TRACE(XERR, "problems removing "<<srcentry<<"; error: "<<-rc);
1463 break;
1464 }
1465 } else {
1466 // Move the entry
1467 if (rename(srcentry.c_str(), dstentry.c_str()) != 0) {
1468 rc = -errno;
1469 TRACE(XERR, "problems moving "<<srcentry<<" to "<<dstentry<<"; error: "<<-rc);
1470 break;
1471 }
1472 }
1473 }
1474 // Close the directory
1475 closedir(dir);
1476
1477 // Done
1478 return rc;
1479}
1480
1481////////////////////////////////////////////////////////////////////////////////
1482/// Set access (opt == 1), modify (opt =2 ) or access&modify (opt = 0, default)
1483/// times of path to current time.
1484/// Returns 0 on success, -errno on failure
1485
1486int XrdProofdAux::Touch(const char *path, int opt)
1487{
1488 if (opt == 0) {
1489 if (utime(path, 0) != 0)
1490 return -errno;
1491 } else if (opt <= 2) {
1492 struct stat st;
1493 if (stat(path, &st) != 0)
1494 return -errno;
1495 struct utimbuf ut = {0,0};
1496 if (opt == 1) {
1497 ut.actime = time(0);
1498 ut.modtime = st.st_mtime;
1499 } else if (opt == 2) {
1500 ut.modtime = time(0);
1501 ut.actime = st.st_atime;
1502 }
1503 if (utime(path, &ut) != 0)
1504 return -errno;
1505 } else {
1506 // Unknown option
1507 return -1;
1508 }
1509 // Done
1510 return 0;
1511}
1512
1513////////////////////////////////////////////////////////////////////////////////
1514/// Receive 'msg' from pipe fd
1515
1516int XrdProofdAux::ReadMsg(int fd, XrdOucString &msg)
1517{
1518 XPDLOC(AUX, "Aux::ReadMsg")
1519
1520 msg = "";
1521 if (fd > 0) {
1522
1523 // Read message length
1524 int len = 0;
1525 if (read(fd, &len, sizeof(len)) != sizeof(len))
1526 return -errno;
1527 TRACE(HDBG,fd<<": len: "<<len);
1528
1529 // Read message
1530 char buf[XPD_MAXLEN];
1531 int nr = -1;
1532 do {
1533 int wanted = (len > XPD_MAXLEN-1) ? XPD_MAXLEN-1 : len;
1534 while ((nr = read(fd, buf, wanted)) < 0 &&
1535 errno == EINTR)
1536 errno = 0;
1537 if (nr < wanted) {
1538 break;
1539 } else {
1540 buf[nr] = '\0';
1541 msg += buf;
1542 }
1543 // Update counters
1544 len = (nr >= len) ? 0 : len - nr;
1545 } while (nr > 0 && len > 0);
1546
1547 TRACE(HDBG,fd<<": buf: "<<buf);
1548
1549 // Done
1550 return 0;
1551 }
1552 // Undefined socket
1553 TRACE(XERR, "pipe descriptor undefined: "<<fd);
1554 return -1;
1555}
1556
1557////////////////////////////////////////////////////////////////////////////////
1558/// Parse a path in the form of "<before>[.<pid>][.<after>]", filling 'rest'
1559/// and returning 'pid'.
1560/// Return 0 if pid is not defined; 'before' is filled with the string preceding
1561/// <pid>, <after> with the string following <pid>.
1562
1563int XrdProofdAux::ParsePidPath(const char *path,
1564 XrdOucString &before, XrdOucString &after)
1565{
1566 XPDLOC(AUX, "ParsePidPath")
1567
1568 before = "";
1569 after = "";
1570 long int pid = -1;
1571 if (path && strlen(path)) {
1572 pid = 0;
1573 int from = 0;
1574 XrdOucString spid, s(path);
1575 bool nopid = 1;
1576 while ((from = s.tokenize(spid, from, '.')) != -1) {
1577 if (spid.length() > 0) {
1578 if (spid.isdigit()) {
1579 // Get pid
1580 pid = (int) spid.atoi();
1581 if (!XPD_LONGOK(pid)) {
1582 // Substring is not a PID
1583 pid = 0;
1584 }
1585 }
1586 if (nopid && pid > 0) {
1587 nopid = 0;
1588 } else if (nopid) {
1589 if (before.length() > 0) before += ".";
1590 before += spid;
1591 } else {
1592 if (after.length() > 0) after += ".";
1593 after += spid;
1594 }
1595 }
1596 }
1597 if (pid == 0 && before.length() == 0) {
1598 before = after;
1599 after = "";
1600 }
1601 }
1602
1603 TRACE(HDBG,"path: "<<(path ? path : "<nul>")<<" --> before: '"<<before
1604 <<"', pid: "<<pid<<", after: '"<<after<<"'");
1605
1606 // Done
1607 return pid;
1608}
1609
1610////////////////////////////////////////////////////////////////////////////////
1611/// Parse a path in the form of "<usr>[.<grp>][.<pid>]", filling 'usr' and 'grp'.
1612/// Returns -1 on failure, 0 if the pid is not defined or the pid.
1613
1614int XrdProofdAux::ParseUsrGrp(const char *path, XrdOucString &usr, XrdOucString &grp)
1615{
1616 XrdOucString rest, after;
1617 int pid = ParsePidPath(path, rest, after);
1618
1619 if (pid >= 0 && rest.length() > 0) {
1620 // Fill 'usr' (everything until the last dot)
1621 usr = rest;
1622 int ip = STR_NPOS;
1623 if ((ip = rest.rfind('.')) != STR_NPOS) {
1624 usr.erase(ip);
1625 // Fill 'grp'
1626 grp = rest;
1627 grp.erase(0, ip + 1);
1628 }
1629 }
1630 // Done
1631 return pid;
1632}
1633
1634//
1635// Functions to process directives for integer and strings
1636//
1637
1638////////////////////////////////////////////////////////////////////////////////
1639/// Generic class directive processor
1640
1641int DoDirectiveClass(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
1642{
1643 if (!d || !(d->fVal))
1644 // undefined inputs
1645 return -1;
1646
1647 return ((XrdProofdConfig *)d->fVal)->DoDirective(d, val, cfg, rcf);
1648}
1649
1650////////////////////////////////////////////////////////////////////////////////
1651/// Process directive for an integer
1652
1653int DoDirectiveInt(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
1654{
1655 XPDLOC(AUX, "DoDirectiveInt")
1656
1657 if (!d || !(d->fVal) || !val)
1658 // undefined inputs
1659 return -1;
1660
1661 if (rcf && !d->fRcf)
1662 // Not re-configurable: do nothing
1663 return 0;
1664
1665 // Check deprecated 'if' directive
1666 if (d->fHost && cfg)
1667 if (XrdProofdAux::CheckIf(cfg, d->fHost) == 0)
1668 return 0;
1669
1670 long int v = strtol(val,0,10);
1671 *((int *)d->fVal) = v;
1672
1673 TRACE(DBG, "set "<<d->fName<<" to "<<*((int *)d->fVal));
1674
1675 return 0;
1676}
1677
1678////////////////////////////////////////////////////////////////////////////////
1679/// Process directive for a string
1680
1681int DoDirectiveString(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
1682{
1683 XPDLOC(AUX, "DoDirectiveString")
1684
1685 if (!d || !(d->fVal) || !val)
1686 // undefined inputs
1687 return -1;
1688
1689 if (rcf && !d->fRcf)
1690 // Not re-configurable: do nothing
1691 return 0;
1692
1693 // Check deprecated 'if' directive
1694 if (d->fHost && cfg)
1695 if (XrdProofdAux::CheckIf(cfg, d->fHost) == 0)
1696 return 0;
1697
1698 *((XrdOucString *)d->fVal) = val;
1699
1700 TRACE(DBG, "set "<<d->fName<<" to "<<*((XrdOucString *)d->fVal));
1701 return 0;
1702}
1703
1704////////////////////////////////////////////////////////////////////////////////
1705/// Set host field for directive 'd' to (const char *h)
1706
1707int SetHostInDirectives(const char *, XrdProofdDirective *d, void *h)
1708{
1709 const char *host = (const char *)h;
1710
1711 if (!d || !host || strlen(host) <= 0)
1712 // Dataset root dir undefined: we cannot continue
1713 return 1;
1714
1715 d->fHost = host;
1716
1717 // Process next
1718 return 0;
1719}
1720
1721//
1722// XrdProofdPipe: class implementing pipe functionality
1723//
1724////////////////////////////////////////////////////////////////////////////////
1725/// Constructor: create the pipe
1726
1728{
1729 // Init pipe for the poller
1730 if (pipe(fPipe) != 0) {
1731 fPipe[0] = -1;
1732 fPipe[1] = -1;
1733 }
1734}
1735
1736////////////////////////////////////////////////////////////////////////////////
1737/// Destructor
1738
1740{
1741 // Close the pipe
1742 Close();
1743}
1744
1745////////////////////////////////////////////////////////////////////////////////
1746/// If open, close and invalidated the pipe descriptors
1747
1749{
1750 if (IsValid()) {
1751 close(fPipe[0]);
1752 close(fPipe[1]);
1753 fPipe[0] = -1;
1754 fPipe[1] = -1;
1755 }
1756}
1757
1758////////////////////////////////////////////////////////////////////////////////
1759/// Post message on the pipe
1760
1761int XrdProofdPipe::Post(int type, const char *msg)
1762{
1763 XPDLOC(AUX, "Pipe::Post")
1764
1765
1766 if (IsValid()) {
1767 XrdOucString buf;
1768 if (msg && strlen(msg) > 0) {
1769 XPDFORM(buf, "%d %s", type, msg);
1770 } else {
1771 buf += type;
1772 }
1773 TRACE(HDBG, fPipe[1] << ": posting: type: "<<type<<", buf: "<<buf);
1774 int len = buf.length() + 1;
1776 if (write(fPipe[1], &len, sizeof(len)) != sizeof(len))
1777 return -errno;
1778 if (write(fPipe[1], buf.c_str(), len) != len)
1779 return -errno;
1780 // Done
1781 return 0;
1782 }
1783 // Invalid pipe
1784 TRACE(XERR, "pipe is invalid");
1785 return -1;
1786}
1787
1788////////////////////////////////////////////////////////////////////////////////
1789/// Recv message from the pipe
1790
1792{
1793 XPDLOC(AUX, "Pipe::Recv")
1794
1795 if (IsValid()) {
1796 XrdOucString buf;
1798 if (XrdProofdAux::ReadMsg(fPipe[0], buf) != 0)
1799 return -1;
1800 }
1801 TRACE(HDBG, fPipe[0] << ": receiving: msg: "<< buf);
1802 msg.Init(buf.c_str());
1803 // Done
1804 return 0;
1805 }
1806 // Invalid pipe
1807 TRACE(XERR, "pipe is invalid");
1808 return -1;
1809}
1810
1811////////////////////////////////////////////////////////////////////////////////
1812/// Poll over the read pipe for to secs; return whatever poll returns
1813
1815{
1816 XPDLOC(AUX, "Pipe::Poll")
1817
1818 if (IsValid()) {
1819
1820 // Read descriptor
1821 struct pollfd fds_r;
1822 fds_r.fd = fPipe[0];
1823 fds_r.events = POLLIN;
1824
1825 // We wait for processes to communicate a session status change
1826 int pollrc = 0;
1827 int xto = (to > 0) ? to * 1000 : -1;
1828 while ((pollrc = poll(&fds_r, 1, xto)) < 0 && (errno == EINTR)) {
1829 errno = 0;
1830 }
1831 // Done
1832 return (pollrc >= 0) ? pollrc : -errno;
1833 }
1834 // Invalid pipe
1835 TRACE(XERR, "pipe is invalid");
1836 return -1;
1837}
1838
1839//
1840// XpdMsg: class to handle messages received over the pipe
1841//
1842////////////////////////////////////////////////////////////////////////////////
1843/// Init from buffer
1844
1845int XpdMsg::Init(const char *buf)
1846{
1847 XPDLOC(AUX, "Msg::Init")
1848
1849 fType = -1;
1850 fBuf = "";
1851 fFrom = -1;
1852
1853 TRACE(HDBG, "buf: "<< (const char *)(buf ? buf : "+++ empty +++"));
1854
1855 if (buf && strlen(buf) > 0) {
1856 fBuf = buf;
1857 fFrom = 0;
1858 // Extract the type
1859 XrdOucString ctyp;
1860 if ((fFrom = fBuf.tokenize(ctyp, fFrom, ' ')) == -1 || ctyp.length() <= 0) {
1861 TRACE(XERR, "ctyp: "<<ctyp<<" fFrom: "<<fFrom);
1862 fBuf = "";
1863 fFrom = -1;
1864 return -1;
1865 }
1866 fType = ctyp.atoi();
1867 if (!XPD_LONGOK(fType)) {
1868 TRACE(XERR, "ctyp: "<<ctyp<<" fType: "<<fType);
1869 fBuf = "";
1870 fFrom = -1;
1871 return -1;
1872 }
1873 fBuf.erase(0,fFrom);
1874 while (fBuf.beginswith(' '))
1875 fBuf.erase(0, 1);
1876 fFrom = 0;
1877 TRACE(HDBG, fType<<", "<<fBuf);
1878 }
1879 // Done
1880 return 0;
1881}
1882
1883////////////////////////////////////////////////////////////////////////////////
1884/// Get next token and interpret it as an int
1885
1886int XpdMsg::Get(int &i)
1887{
1888 XPDLOC(AUX, "Msg::Get")
1889
1890 TRACE(HDBG,"int &i: "<<fFrom<<" "<<fBuf);
1891
1892 int iold = i;
1893 XrdOucString tkn;
1894 if ((fFrom = fBuf.tokenize(tkn, fFrom, ' ')) == -1 || tkn.length() <= 0)
1895 return -1;
1896 i = tkn.atoi();
1897 if (!XPD_LONGOK(i)) {
1898 TRACE(XERR, "tkn: "<<tkn<<" i: "<<i);
1899 i = iold;
1900 return -1;
1901 }
1902 // Done
1903 return 0;
1904}
1905
1906////////////////////////////////////////////////////////////////////////////////
1907/// Get next token
1908
1909int XpdMsg::Get(XrdOucString &s)
1910{
1911 XPDLOC(AUX, "Msg::Get")
1912
1913 TRACE(HDBG,"XrdOucString &s: "<<fFrom<<" "<<fBuf);
1914
1915 if ((fFrom = fBuf.tokenize(s, fFrom, ' ')) == -1 || s.length() <= 0) {
1916 TRACE(XERR, "s: "<<s<<" fFrom: "<<fFrom);
1917 return -1;
1918 }
1919
1920 // Done
1921 return 0;
1922}
1923
1924////////////////////////////////////////////////////////////////////////////////
1925/// Get next token and interpret it as a pointer
1926
1927int XpdMsg::Get(void **p)
1928{
1929 XPDLOC(AUX, "Msg::Get")
1930
1931 TRACE(HDBG,"void **p: "<<fFrom<<" "<<fBuf);
1932
1933 XrdOucString tkn;
1934 if ((fFrom = fBuf.tokenize(tkn, fFrom, ' ')) == -1 || tkn.length() <= 0) {
1935 TRACE(XERR, "tkn: "<<tkn<<" fFrom: "<<fFrom);
1936 return -1;
1937 }
1938 sscanf(tkn.c_str(), "%p", p);
1939
1940 // Done
1941 return 0;
1942}
1943
1944
1945//
1946// Class to handle condensed multi-string specification, e.g <head>[01-25]<tail>
1947//
1948
1949////////////////////////////////////////////////////////////////////////////////
1950/// Init the multi-string handler.
1951/// Supported formats:
1952/// <head>[1-4]<tail> for <head>1<tail>, ..., <head>4<tail> (4 items)
1953/// <head>[a,b]<tail> for <head>a<tail>, <head>b<tail> (2 items)
1954/// <head>[a,1-3]<tail> for <head>a<tail>, <head>1<tail>, <head>2<tail>,
1955/// <head>3<tail> (4 items)
1956/// <head>[01-15]<tail> for <head>01<tail>, ..., <head>15<tail> (15 items)
1957///
1958/// A dashed is possible only between numerically treatable values, i.e.
1959/// single letters ([a-Z] will take all tokens between 'a' and 'Z') or n-field
1960/// numbers ([001-999] will take all numbers 1 to 999 always using 3 spaces).
1961/// Mixed values (e.g. [a-034]) are not allowed.
1962
1964{
1965 fN = 0;
1966 if (s && strlen(s)) {
1967 XrdOucString kernel(s);
1968 // Find begin of kernel
1969 int ib = kernel.find('[');
1970 if (ib == STR_NPOS) return;
1971 // Find end of kernel
1972 int ie = kernel.find(']', ib + 1);
1973 if (ie == STR_NPOS) return;
1974 // Check kernel length (it must not be empty)
1975 if (ie == ib + 1) return;
1976 // Fill head and tail
1977 fHead.assign(kernel, 0, ib -1);
1978 fTail.assign(kernel, ie + 1);
1979 // The rest is the kernel
1980 XrdOucString tkns(kernel, ib + 1, ie - 1);
1981 // Tokenize the kernel filling the list
1982 int from = 0;
1983 XrdOucString tkn;
1984 while ((from = tkns.tokenize(tkn, from, ',')) != -1) {
1985 if (tkn.length() > 0) {
1986 XrdProofdMultiStrToken t(tkn.c_str());
1987 if (t.IsValid()) {
1988 fN += t.N();
1989 fTokens.push_back(t);
1990 }
1991 }
1992 }
1993 // Reset everything if nothing found
1994 if (!IsValid()) {
1995 fHead = "";
1996 fTail = "";
1997 }
1998 }
1999}
2000
2001////////////////////////////////////////////////////////////////////////////////
2002/// Return true if 's' is compatible with this multi-string
2003
2005{
2006 if (s && strlen(s)) {
2007 XrdOucString str(s);
2008 if (fHead.length() <= 0 || str.beginswith(fHead)) {
2009 if (fTail.length() <= 0 || str.endswith(fTail)) {
2010 str.replace(fHead,"");
2011 str.replace(fTail,"");
2012 std::list<XrdProofdMultiStrToken>::iterator it = fTokens.begin();
2013 for (; it != fTokens.end(); ++it) {
2014 if ((*it).Matches(str.c_str()))
2015 return 1;
2016 }
2017 }
2018 }
2019 }
2020 // Done
2021 return 0;
2022}
2023
2024////////////////////////////////////////////////////////////////////////////////
2025/// Return a string with comma-separated elements
2026
2028{
2029 XrdOucString str(fN * (fHead.length() + fTail.length() + 4)) ;
2030 str = "";
2031 if (fN > 0) {
2032 std::list<XrdProofdMultiStrToken>::iterator it = fTokens.begin();
2033 for (; it != fTokens.end(); ++it) {
2034 int n = (*it).N(), j = -1;
2035 while (n--) {
2036 str += fHead;
2037 str += (*it).Export(j);
2038 str += fTail;
2039 str += ",";
2040 }
2041 }
2042 }
2043 // Remove last ','
2044 if (str.endswith(','))
2045 str.erase(str.rfind(','));
2046 // Done
2047 return str;
2048}
2049
2050////////////////////////////////////////////////////////////////////////////////
2051/// Return i-th combination (i : 0 -> fN-1)
2052
2053XrdOucString XrdProofdMultiStr::Get(int i)
2054{
2055 XrdOucString str;
2056
2057 if (i >= 0) {
2058 std::list<XrdProofdMultiStrToken>::iterator it = fTokens.begin();
2059 for (; it != fTokens.end(); ++it) {
2060 int n = (*it).N(), j = -1;
2061 if ((i + 1) > n) {
2062 i -= n;
2063 } else {
2064 j = i;
2065 str = fHead;
2066 str += (*it).Export(j);
2067 str += fTail;
2068 break;
2069 }
2070 }
2071 }
2072
2073 // Done
2074 return str;
2075}
2076
2077////////////////////////////////////////////////////////////////////////////////
2078/// Init the multi-string token.
2079/// Supported formats:
2080/// [1-4] for 1, ..., 4 (4 items)
2081/// [a,b] for a, b<tail> (2 items)
2082/// [a,1-3] for a, 1, 2, 3 (4 items)
2083/// [01-15] for 01, ..., 15 (15 items)
2084///
2085/// A dashed is possible only between numerically treatable values, i.e.
2086/// single letters ([a-Z] will take all tokens between 'a' and 'Z') or n-field
2087/// numbers ([001-999] will take all numbers 1 to 999 always using 3 spaces).
2088/// Mixed values (e.g. [a-034]) are not allowed.
2089
2091{
2092 XPDLOC(AUX, "MultiStrToken::Init")
2093
2094 fIa = LONG_MAX;
2095 fIb = LONG_MAX;
2096 fType = kUndef;
2097 fN = 0;
2098 bool bad = 0;
2099 XrdOucString emsg;
2100 if (s && strlen(s)) {
2101 fA = s;
2102 // Find the dash, if any
2103 int id = fA.find('-');
2104 if (id == STR_NPOS) {
2105 // Simple token, nothing much to do
2106 fN = 1;
2107 fType = kSimple;
2108 return;
2109 }
2110 // Define the extremes
2111 fB.assign(fA, id + 1);
2112 fA.erase(id);
2113 if (fB.length() <= 0) {
2114 if (fA.length() > 0) {
2115 // Simple token, nothing much to do
2116 fN = 1;
2117 fType = kSimple;
2118 }
2119 // Invalid
2120 return;
2121 }
2122 // Check validity
2123 char *a = (char *)fA.c_str();
2124 char *b = (char *)fB.c_str();
2125 if (fA.length() == 1 && fB.length() == 1) {
2126 LETTOIDX(*a, fIa);
2127 if (fIa != LONG_MAX) {
2128 LETTOIDX(*b, fIb);
2129 if (fIb != LONG_MAX && fIa <= fIb) {
2130 // Ordered single-letter extremes: OK
2131 fType = kLetter;
2132 fN = fIb - fIa + 1;
2133 return;
2134 }
2135 } else if (DIGIT(*a) && DIGIT(*b) &&
2136 (fIa = *a) <= (fIb = *b)) {
2137 // Ordered single-digit extremes: OK
2138 fType = kDigit;
2139 fN = fIb - fIa + 1;
2140 return;
2141 }
2142 // Not-supported single-field extremes
2143 emsg = "not-supported single-field extremes";
2144 bad = 1;
2145 }
2146 if (!bad) {
2147 fIa = fA.atoi();
2148 if (fIa != LONG_MAX && fIa != LONG_MIN) {
2149 fIb = fB.atoi();
2150 if (fIb != LONG_MAX && fIb != LONG_MIN && fIb >= fIa) {
2151 fType = kDigits;
2152 fN = fIb - fIa + 1;
2153 return;
2154 }
2155 // Not-supported single-field extremes
2156 emsg = "non-digit or wrong-ordered extremes";
2157 bad = 1;
2158 } else {
2159 // Not-supported single-field extremes
2160 emsg = "non-digit extremes";
2161 bad = 1;
2162 }
2163 }
2164 }
2165 // Print error message, if any
2166 if (bad) {
2167 TRACE(XERR, emsg);
2168 fA = "";
2169 fB = "";
2170 fIa = LONG_MAX;
2171 fIb = LONG_MAX;
2172 }
2173 // Done
2174 return;
2175}
2176
2177////////////////////////////////////////////////////////////////////////////////
2178/// Return true if 's' is compatible with this token
2179
2181{
2182 if (s && strlen(s)) {
2183 if (fType == kSimple)
2184 return ((fA == s) ? 1 : 0);
2185 // Multiple one: parse it
2186 XrdOucString str(s);
2187 long ls = LONG_MIN;
2188 if (fType != kDigits) {
2189 if (str.length() > 1)
2190 return 0;
2191 char *ps = (char *)s;
2192 if (fType == kDigit) {
2193 if (!DIGIT(*ps) || *ps < fIa || *ps > fIb)
2194 return 0;
2195 } else if (fType == kLetter) {
2196 LETTOIDX(*ps, ls);
2197 if (ls == LONG_MAX || ls < fIa || ls > fIb)
2198 return 0;
2199 }
2200 } else {
2201 ls = str.atoi();
2202 if (ls == LONG_MAX || ls < fIa || ls > fIb)
2203 return 0;
2204 }
2205 // OK
2206 return 1;
2207 }
2208 // Undefined
2209 return 0;
2210}
2211
2212////////////////////////////////////////////////////////////////////////////////
2213/// Export 'next' token; use next < 0 start from the first
2214
2215XrdOucString XrdProofdMultiStrToken::Export(int &next)
2216{
2217 XrdOucString tkn(fA.length());
2218
2219 // If simple, return the one we have
2220 if (fType == kSimple)
2221 return (tkn = fA);
2222
2223 // Check if we still have something
2224 if (next > fIb - fIa)
2225 return tkn;
2226
2227 // Check where we are
2228 if (next == -1)
2229 next = 0;
2230
2231 // If letters we need to found the right letter
2232 if (fType == kLetter) {
2233 char c = 0;
2234 IDXTOLET(fIa + next, c);
2235 next++;
2236 return (tkn = c);
2237 }
2238
2239 // If single digit, add the offset
2240 if (fType == kDigit) {
2241 tkn = (char)(fIa + next);
2242 next++;
2243 return tkn;
2244 }
2245
2246 // If digits, check if we need to pad 0's
2247 XrdOucString tmp(fA.length());
2248 tmp.form("%ld", fIa + next);
2249 next++;
2250 int dl = fA.length() - tmp.length();
2251 if (dl <= 0) return tmp;
2252 // Add padding 0's
2253 tkn = "";
2254 while (dl--) tkn += "0";
2255 tkn += tmp;
2256 return tkn;
2257}
2258
2259////////////////////////////////////////////////////////////////////////////////
2260/// Recreate the string according to 'fmt', the up to 5 'const char *',
2261/// up to 6 'int' arguments, up to 5 'void *' and up to 1 unsigned integer.
2262
2263void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2264 int ns, const char *ss[5],
2265 int ni, int ii[6],
2266 int np, void *pp[5],
2267 int nu, unsigned int ui)
2268{
2269 int len = 0;
2270 if (!fmt || (len = strlen(fmt)) <= 0) return;
2271
2272 char si[32], sp[32];
2273
2274 // Estimate length
2275 int i = ns;
2276 while (i-- > 0) { if (ss[i]) { len += strlen(ss[i]); } }
2277 i = ni + np;
2278 while (i-- > 0) { len += 32; }
2279
2280 s.resize(len+1);
2281
2282 int from = 0;
2283 s.assign(fmt, from);
2284 int nii = 0, nss = 0, npp = 0, nui = 0;
2285 int k = STR_NPOS;
2286 while ((k = s.find('%', from)) != STR_NPOS) {
2287 bool replaced = 0;
2288 if (s[k+1] == 's') {
2289 if (nss < ns) {
2290 s.replace("%s", ss[nss++], k, k + 1);
2291 replaced = 1;
2292 }
2293 } else if (s[k+1] == 'd') {
2294 if (nii < ni) {
2295 snprintf(si, 32, "%d", ii[nii++]);
2296 s.replace("%d", si, k, k + 1);
2297 replaced = 1;
2298 }
2299 } else if (s[k+1] == 'u') {
2300 if (nui < nu) {
2301 snprintf(si, 32, "%u", ui);
2302 s.replace("%u", si, k, k + 1);
2303 replaced = 1;
2304 }
2305 } else if (s[k+1] == 'p') {
2306 if (npp < np) {
2307 snprintf(sp, 32, "%p", pp[npp++]);
2308 s.replace("%p", sp, k, k + 1);
2309 replaced = 1;
2310 }
2311 }
2312 if (!replaced) from = k + 1;
2313 }
2314}
2315
2316////////////////////////////////////////////////////////////////////////////////
2317/// Recreate the string according to 'fmt' and the 5 'const char *' arguments
2318
2319void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2320 const char *s0, const char *s1,
2321 const char *s2, const char *s3, const char *s4)
2322{
2323 const char *ss[5] = {s0, s1, s2, s3, s4};
2324 int ii[6] = {0,0,0,0,0,0};
2325 void *pp[5] = {0,0,0,0,0};
2326
2327 XrdProofdAux::Form(s,fmt,5,ss,0,ii,0,pp);
2328}
2329
2330////////////////////////////////////////////////////////////////////////////////
2331/// Recreate the string according to 'fmt' and the 5 'int' arguments
2332
2333void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0,
2334 int i1, int i2, int i3, int i4, int i5)
2335{
2336 const char *ss[5] = {0, 0, 0, 0, 0};
2337 int ii[6] = {i0,i1,i2,i3,i4,i5};
2338 void *pp[5] = {0,0,0,0,0};
2339
2340 XrdProofdAux::Form(s,fmt,0,ss,6,ii,5,pp);
2341}
2342
2343////////////////////////////////////////////////////////////////////////////////
2344/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2345
2346void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2347 void *p0, void *p1, void *p2, void *p3, void *p4)
2348{
2349 const char *ss[5] = {0, 0, 0, 0, 0};
2350 int ii[6] = {0,0,0,0,0,0};
2351 void *pp[5] = {p0,p1,p2,p3,p4};
2352
2353 XrdProofdAux::Form(s,fmt,0,ss,0,ii,5,pp);
2354}
2355
2356
2357////////////////////////////////////////////////////////////////////////////////
2358/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2359
2360void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0, const char *s0,
2361 const char *s1, const char *s2, const char *s3)
2362{
2363 const char *ss[5] = {s0, s1, s2, s3, 0};
2364 int ii[6] = {i0,0,0,0,0,0};
2365 void *pp[5] = {0,0,0,0,0};
2366
2367 XrdProofdAux::Form(s,fmt,4,ss,1,ii,0,pp);
2368}
2369
2370////////////////////////////////////////////////////////////////////////////////
2371/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2372
2373void XrdProofdAux::Form(XrdOucString &s, const char *fmt, const char *s0,
2374 int i0, int i1, int i2, int i3)
2375{
2376 const char *ss[5] = {s0,0,0,0,0};
2377 int ii[6] = {i0,i1,i2,i3,0,0};
2378 void *pp[5] = {0,0,0,0,0};
2379
2380 XrdProofdAux::Form(s,fmt,1,ss,4,ii,0,pp);
2381}
2382
2383////////////////////////////////////////////////////////////////////////////////
2384/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2385
2386void XrdProofdAux::Form(XrdOucString &s, const char *fmt, const char *s0,
2387 int i0, int i1, unsigned int ui)
2388{
2389 const char *ss[5] = {s0,0,0,0,0};
2390 int ii[6] = {i0,i1,0,0,0,0};
2391 void *pp[5] = {0,0,0,0,0};
2392
2393 XrdProofdAux::Form(s,fmt,1,ss,2,ii,0,pp, 1, ui);
2394}
2395
2396////////////////////////////////////////////////////////////////////////////////
2397/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2398
2399void XrdProofdAux::Form(XrdOucString &s, const char *fmt, const char *s0, const char *s1,
2400 int i0, int i1, int i2)
2401{
2402 const char *ss[5] = {s0,s1,0,0,0};
2403 int ii[6] = {i0,i1,i2,0,0,0};
2404 void *pp[5] = {0,0,0,0,0};
2405
2406 XrdProofdAux::Form(s,fmt,2,ss,3,ii,0,pp);
2407}
2408
2409////////////////////////////////////////////////////////////////////////////////
2410/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2411
2412void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0, int i1,
2413 const char *s0, const char *s1, const char *s2)
2414{
2415 const char *ss[5] = {s0,s1,s2,0,0};
2416 int ii[6] = {i0,i1,0,0,0,0};
2417 void *pp[5] = {0,0,0,0,0};
2418
2419 XrdProofdAux::Form(s,fmt,3,ss,2,ii,0,pp);
2420}
2421
2422
2423////////////////////////////////////////////////////////////////////////////////
2424/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2425
2426void XrdProofdAux::Form(XrdOucString &s, const char *fmt, const char *s0,
2427 const char *s1, const char *s2,
2428 int i0, int i1,
2429 const char *s3, const char *s4)
2430{
2431 const char *ss[5] = {s0,s1,s2,s3,s4};
2432 int ii[6] = {i0,i1,0,0,0,0};
2433 void *pp[5] = {0,0,0,0,0};
2434
2435 XrdProofdAux::Form(s,fmt,5,ss,2,ii,0,pp);
2436}
2437
2438////////////////////////////////////////////////////////////////////////////////
2439/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2440
2441void XrdProofdAux::Form(XrdOucString &s, const char *fmt, const char *s0,
2442 int i0, int i1, const char *s1,
2443 const char *s2, const char *s3)
2444{
2445 const char *ss[5] = {s0,s1,s2,s3,0};
2446 int ii[6] = {i0,i1,0,0,0,0};
2447 void *pp[5] = {0,0,0,0,0};
2448
2449 XrdProofdAux::Form(s,fmt,4,ss,2,ii,0,pp);
2450}
2451
2452////////////////////////////////////////////////////////////////////////////////
2453/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2454
2455void XrdProofdAux::Form(XrdOucString &s, const char *fmt, const char *s0,
2456 const char *s1, const char *s2,
2457 int i0, unsigned int ui)
2458{
2459 const char *ss[5] = {s0,s1,s2,0,0};
2460 int ii[6] = {i0,0,0,0,0,0};
2461 void *pp[5] = {0,0,0,0,0};
2462
2463 XrdProofdAux::Form(s,fmt,3,ss,1,ii,0,pp, 1, ui);
2464}
2465
2466////////////////////////////////////////////////////////////////////////////////
2467/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2468
2469void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0, int i1, int i2,
2470 const char *s0, const char *s1)
2471{
2472 const char *ss[5] = {s0,s1,0,0,0};
2473 int ii[6] = {i0,i1,i2,0,0,0};
2474 void *pp[5] = {0,0,0,0,0};
2475
2476 XrdProofdAux::Form(s,fmt,2,ss,3,ii,0,pp);
2477}
2478
2479
2480////////////////////////////////////////////////////////////////////////////////
2481/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2482
2483void XrdProofdAux::Form(XrdOucString &s, const char *fmt, const char *s0,
2484 const char *s1, const char *s2, const char *s3, int i0)
2485{
2486 const char *ss[5] = {s0,s1,s2,s3,0};
2487 int ii[6] = {i0,0,0,0,0,0};
2488 void *pp[5] = {0,0,0,0,0};
2489
2490 XrdProofdAux::Form(s,fmt,4,ss,1,ii,0,pp);
2491}
2492
2493////////////////////////////////////////////////////////////////////////////////
2494/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2495
2496void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0, int i1, int i2,
2497 int i3, const char *s0)
2498{
2499 const char *ss[5] = {s0,0,0,0,0};
2500 int ii[6] = {i0,i1,i2,i3,0,0};
2501 void *pp[5] = {0,0,0,0,0};
2502
2503 XrdProofdAux::Form(s,fmt,1,ss,4,ii,0,pp);
2504}
2505
2506////////////////////////////////////////////////////////////////////////////////
2507/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2508
2509void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0, int i1, void *p0)
2510{
2511 const char *ss[5] = {0,0,0,0,0};
2512 int ii[6] = {i0,i1,0,0,0,0};
2513 void *pp[5] = {p0,0,0,0,0};
2514
2515 XrdProofdAux::Form(s,fmt,0,ss,2,ii,1,pp);
2516}
2517
2518////////////////////////////////////////////////////////////////////////////////
2519/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2520
2521void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2522 int i0, int i1, int i2, void *p0)
2523{
2524 const char *ss[5] = {0,0,0,0,0};
2525 int ii[6] = {i0,i1,i2,0,0,0};
2526 void *pp[5] = {p0,0,0,0,0};
2527
2528 XrdProofdAux::Form(s,fmt,0,ss,3,ii,1,pp);
2529}
2530
2531////////////////////////////////////////////////////////////////////////////////
2532/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2533
2534void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2535 int i0, int i1, int i2, int i3, void *p0)
2536{
2537 const char *ss[5] = {0,0,0,0,0};
2538 int ii[6] = {i0,i1,i2,i3,0,0};
2539 void *pp[5] = {p0,0,0,0,0};
2540
2541 XrdProofdAux::Form(s,fmt,0,ss,4,ii,1,pp);
2542}
2543
2544////////////////////////////////////////////////////////////////////////////////
2545/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2546
2547void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0, int i1,
2548 void *p0, int i2, int i3)
2549{
2550 const char *ss[5] = {0,0,0,0,0};
2551 int ii[6] = {i0,i1,i2,i3,0,0};
2552 void *pp[5] = {p0,0,0,0,0};
2553
2554 XrdProofdAux::Form(s,fmt,0,ss,4,ii,1,pp);
2555}
2556
2557////////////////////////////////////////////////////////////////////////////////
2558/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2559
2560void XrdProofdAux::Form(XrdOucString &s, const char *fmt, void *p0, int i0, int i1)
2561{
2562 const char *ss[5] = {0,0,0,0,0};
2563 int ii[6] = {i0,i1,0,0,0,0};
2564 void *pp[5] = {p0,0,0,0,0};
2565
2566 XrdProofdAux::Form(s,fmt,0,ss,2,ii,1,pp);
2567}
2568
2569////////////////////////////////////////////////////////////////////////////////
2570/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2571
2572void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2573 const char *s0, void *p0, int i0, int i1)
2574{
2575 const char *ss[5] = {s0,0,0,0,0};
2576 int ii[6] = {i0,i1,0,0,0,0};
2577 void *pp[5] = {p0,0,0,0,0};
2578
2579 XrdProofdAux::Form(s,fmt,1,ss,2,ii,1,pp);
2580}
2581
2582////////////////////////////////////////////////////////////////////////////////
2583/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2584
2585void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2586 void *p0, const char *s0, int i0)
2587{
2588 const char *ss[5] = {s0,0,0,0,0};
2589 int ii[6] = {i0,0,0,0,0,};
2590 void *pp[5] = {p0,0,0,0,0};
2591
2592 XrdProofdAux::Form(s,fmt,1,ss,1,ii,1,pp);
2593}
2594
2595////////////////////////////////////////////////////////////////////////////////
2596/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2597
2598void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2599 const char *s0, const char *s1, void *p0)
2600{
2601 const char *ss[5] = {s0,s1,0,0,0};
2602 int ii[6] = {0,0,0,0,0,0};
2603 void *pp[5] = {p0,0,0,0,0};
2604
2605 XrdProofdAux::Form(s,fmt,2,ss,0,ii,1,pp);
2606}
2607
2608////////////////////////////////////////////////////////////////////////////////
2609/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2610
2611void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0,
2612 const char *s0, const char *s1, int i1, int i2)
2613{
2614 const char *ss[5] = {s0,s1,0,0,0};
2615 int ii[6] = {i0,i1,i2,0,0,0};
2616 void *pp[5] = {0,0,0,0,0};
2617
2618 XrdProofdAux::Form(s,fmt,2,ss,3,ii,0,pp);
2619}
2620
2621////////////////////////////////////////////////////////////////////////////////
2622/// Recreate the string according to 'fmt' and the 5 'void *' arguments
2623
2624void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0,
2625 const char *s0, int i1, int i2)
2626{
2627 const char *ss[5] = {s0,0,0,0,0};
2628 int ii[6] = {i0,i1,i2,0,0,0};
2629 void *pp[5] = {0,0,0,0,0};
2630
2631 XrdProofdAux::Form(s,fmt,1,ss,3,ii,0,pp);
2632}
2633
SVector< double, 2 > v
Definition: Dict.h:5
#define d(i)
Definition: RSha256.hxx:102
#define b(i)
Definition: RSha256.hxx:100
#define c(i)
Definition: RSha256.hxx:101
#define s0(x)
Definition: RSha256.hxx:90
#define s1(x)
Definition: RSha256.hxx:91
#define h(i)
Definition: RSha256.hxx:106
static double p3(double t, double a, double b, double c, double d)
static double p1(double t, double a, double b)
static double p2(double t, double a, double b, double c)
#define TRACE(Flag, Args)
Definition: TGHtml.h:120
int type
Definition: TGX11.cxx:120
@ kXP_Undef
@ kUndef
#define XrdSysError
Definition: XpdSysError.h:8
#define XrdSysLogger
Definition: XpdSysLogger.h:8
int SetHostInDirectives(const char *, XrdProofdDirective *d, void *h)
Set host field for directive 'd' to (const char *h)
#define XPD_MAXLEN
int DoDirectiveInt(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
Process directive for an integer.
int DoDirectiveClass(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
Generic class directive processor.
int DoDirectiveString(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
Process directive for a string.
#define DIGIT(x)
Definition: XrdProofdAux.h:349
#define IDXTOLET(ilet, x)
Definition: XrdProofdAux.h:358
#define XPDFORM
Definition: XrdProofdAux.h:381
#define LETTOIDX(x, ilet)
Definition: XrdProofdAux.h:353
#define SafeFree(x)
Definition: XrdProofdAux.h:341
#define XpdBadPGuard(g, u)
Definition: XrdProofdAux.h:368
#define XPD_LONGOK(x)
#define XPDLOC(d, x)
#define XrdSysMutexHelper
Definition: XrdSysToOuc.h:17
#define XrdSysRecMutex
Definition: XrdSysToOuc.h:18
#define free
Definition: civetweb.c:1539
#define snprintf
Definition: civetweb.c:1540
#define malloc
Definition: civetweb.c:1536
static struct mg_connection * fc(struct mg_context *ctx)
Definition: civetweb.c:3728
int fFrom
Definition: XrdProofdAux.h:180
XrdOucString fBuf
Definition: XrdProofdAux.h:179
int Get(int &i)
Get next token and interpret it as an int.
int fType
Definition: XrdProofdAux.h:178
int Init(const char *buf)
Init from buffer.
XrdOucString fGroup
Definition: XrdProofdAux.h:61
XrdOucString fUser
Definition: XrdProofdAux.h:40
XrdOucString fHomeDir
Definition: XrdProofdAux.h:42
static int ChangeOwn(const char *path, XrdProofUI ui)
Change the ownership of 'path' to the entity described by 'ui'.
static int GetUserInfo(const char *usr, XrdProofUI &ui)
Get information about user 'usr' in a thread safe way.
static int MvDir(const char *oldpath, const char *newpath)
Move content of directory at oldpath to newpath.
static int Touch(const char *path, int opt=0)
Set access (opt == 1), modify (opt =2 ) or access&modify (opt = 0, default) times of path to current ...
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,...
static int ParseUsrGrp(const char *path, XrdOucString &usr, XrdOucString &grp)
Parse a path in the form of "<usr>[.<grp>][.<pid>]", filling 'usr' and 'grp'.
static int AssertDir(const char *path, XrdProofUI ui, bool changeown)
Make sure that 'path' exists and is owned by the entity described by 'ui'.
static int VerifyProcessByID(int pid, const char *pname="proofserv")
Check if a process named 'pname' and process 'pid' is still in the process table.
static long int GetLong(char *str)
Extract first integer from string at 'str', if any.
static const char * ProofRequestTypes(int type)
Translates the proof request type in a human readable string.
static int KillProcess(int pid, bool forcekill, XrdProofUI ui, bool changeown)
Kill the process 'pid'.
static bool HasToken(const char *s, const char *tokens)
Returns true is 's' contains at least one of the comma-separated tokens in 'tokens'.
static int GetGroupInfo(const char *grp, XrdProofGI &gi)
Get information about group with 'gid' in a thread safe way.
static int ChangeToDir(const char *dir, XrdProofUI ui, bool changeown)
Change current directory to 'dir'.
static int ChangeMod(const char *path, unsigned int mode)
Change the permission mode of 'path' to 'mode'.
static int GetNumCPUs()
Find out and return the number of CPUs in the local machine.
static int GetProcesses(const char *pn, std::map< int, XrdOucString > *plist)
Get from the process table list of PIDs for processes named "proofserv' For {linux,...
static int ReadMsg(int fd, XrdOucString &msg)
Receive 'msg' from pipe fd.
static int GetIDFromPath(const char *path, XrdOucString &emsg)
Extract an integer from a file.
static int Write(int fd, const void *buf, size_t nb)
Write nb bytes at buf to descriptor 'fd' ignoring interrupts Return the number of bytes written or -1...
static XrdSysRecMutex fgFormMutex
Definition: XrdProofdAux.h:248
static void LogEmsgToFile(const char *flog, const char *emsg, const char *pfx=0)
Logs error message 'emsg' to file 'flog' using standard technology.
static int RmDir(const char *path)
Remove directory at path and its content.
static int SymLink(const char *path, const char *link)
Create a symlink 'link' to 'path' Return 0 in case of success, -1 in case of error.
static const char * AdminMsgType(int type)
Translates the admin message type in a human readable string.
static int CheckIf(XrdOucStream *s, const char *h)
Check existence and match condition of an 'if' directive If none (valid) is found,...
static char * Expand(char *p)
Expand path 'p' relative to: $HOME if begins with ~/ <user>'s $HOME if begins with ~<user>/ $PWD if d...
static int ParsePidPath(const char *path, XrdOucString &before, XrdOucString &after)
Parse a path in the form of "<before>[.<pid>][.<after>]", filling 'rest' and returning 'pid'.
static int AssertBaseDir(const char *path, XrdProofUI ui)
Make sure that the base dir of 'path' is either owned by 'ui' or gives full permissions to 'ui'.
XrdOucString Export(int &next)
Export 'next' token; use next < 0 start from the first.
bool Matches(const char *s)
Return true if 's' is compatible with this token.
void Init(const char *s)
Init the multi-string token.
XrdOucString fTail
Definition: XrdProofdAux.h:157
XrdOucString Export()
Return a string with comma-separated elements.
void Init(const char *s)
Init the multi-string handler.
std::list< XrdProofdMultiStrToken > fTokens
Definition: XrdProofdAux.h:158
XrdOucString Get(int i)
Return i-th combination (i : 0 -> fN-1)
bool IsValid() const
Definition: XrdProofdAux.h:167
bool Matches(const char *s)
Return true if 's' is compatible with this multi-string.
XrdOucString fHead
Definition: XrdProofdAux.h:156
bool IsValid() const
Definition: XrdProofdAux.h:209
int Recv(XpdMsg &msg)
Recv message from the pipe.
int Poll(int to=-1)
Poll over the read pipe for to secs; return whatever poll returns.
void Close()
If open, close and invalidated the pipe descriptors.
XrdProofdPipe()
Constructor: create the pipe.
virtual ~XrdProofdPipe()
Destructor.
XrdSysRecMutex fRdMtx
Definition: XrdProofdAux.h:201
XrdSysRecMutex fWrMtx
Definition: XrdProofdAux.h:202
int Post(int type, const char *msg)
Post message on the pipe.
TLine * line
const Int_t n
Definition: legend1.C:16
TGraphErrors * gr
Definition: legend1.C:25
static constexpr double s
static constexpr double ps
static constexpr double ns
int changeown(const std::string &path, uid_t u, gid_t g)
Change the ownership of 'path' to the entity described by {u,g}.
Definition: proofexecv.cxx:738
int pw_gid
Definition: TWinNTSystem.h:51
int pw_uid
Definition: TWinNTSystem.h:50
char * pw_name
Definition: TWinNTSystem.h:48
char * pw_dir
Definition: TWinNTSystem.h:54
auto * a
Definition: textangle.C:12