Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
43XrdSysRecMutex XrdProofdAux::fgFormMutex;
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;
1775 XrdSysMutexHelper mh(fWrMtx);
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;
1797 { XrdSysMutexHelper mh(fRdMtx);
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
1963void XrdProofdMultiStr::Init(const char *s)
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
#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 a(i)
Definition RSha256.hxx:99
#define s1(x)
Definition RSha256.hxx:91
#define h(i)
Definition RSha256.hxx:106
#define TRACE(Flag, Args)
Definition TGHtml.h:121
XFontStruct * id
Definition TGX11.cxx:109
char name[80]
Definition TGX11.cxx:110
int type
Definition TGX11.cxx:121
@ kXP_Undef
@ kUndef
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)
#define IDXTOLET(ilet, x)
#define XPDFORM
#define LETTOIDX(x, ilet)
#define SafeFree(x)
#define XpdBadPGuard(g, u)
#define XPD_LONGOK(x)
#define XPDLOC(d, x)
#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
XrdOucString fBuf
int Get(int &i)
Get next token and interpret it as an int.
int Init(const char *buf)
Init from buffer.
XrdOucString fGroup
XrdOucString fUser
XrdOucString fHomeDir
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
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
XrdOucString Export()
Return a string with comma-separated elements.
void Init(const char *s)
Init the multi-string handler.
std::list< XrdProofdMultiStrToken > fTokens
XrdOucString Get(int i)
Return i-th combination (i : 0 -> fN-1)
bool IsValid() const
bool Matches(const char *s)
Return true if 's' is compatible with this multi-string.
XrdOucString fHead
bool IsValid() const
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
XrdSysRecMutex fWrMtx
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
int changeown(const std::string &path, uid_t u, gid_t g)
Change the ownership of 'path' to the entity described by {u,g}.
int pw_gid
int pw_uid
char * pw_name
char * pw_dir