Logo ROOT   6.14/05
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 
97 char *XrdProofdAux::Expand(char *p)
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 
191 void 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 
202 long 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 
225 int 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 
293 int 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 
365 int 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 
394 void 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 
430 int 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 
467 int XrdProofdAux::AssertBaseDir(const char *path, XrdProofUI ui)
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 
511 int 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 
568 int 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 
657 int 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 
695 int 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 
725 int 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 
837 int 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 
921 int 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 
1110 int 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 
1135 bool 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 
1153 int 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)) {
1191  if (XrdProofdAux::HasToken(line, pn))
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 
1293 int 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 
1346 int 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 
1409 int 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 
1486 int 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 
1516 int 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 
1563 int 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 
1614 int 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 
1641 int 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 
1653 int 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 
1681 int 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 
1707 int 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 
1761 int 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 
1845 int 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 
1886 int 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 
1909 int 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 
1927 int 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 
1963 void 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 
2053 XrdOucString 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 
2215 XrdOucString 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 
2263 void 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 
2319 void 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 
2333 void 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 
2346 void 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 
2360 void 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 
2373 void 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 
2386 void 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 
2399 void 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 
2412 void 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 
2426 void 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 
2441 void 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 
2455 void 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 
2469 void 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 
2483 void 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 
2496 void 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 
2509 void 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 
2521 void 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 
2534 void 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 
2547 void 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 
2560 void 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 
2572 void 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 
2585 void 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 
2598 void 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 
2611 void 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 
2624 void 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 
static int GetNumCPUs()
Find out and return the number of CPUs in the local machine.
#define XPD_MAXLEN
#define XrdSysLogger
Definition: XpdSysLogger.h:8
static int Write(int fd, const void *buf, size_t nb)
Write nb bytes at buf to descriptor &#39;fd&#39; ignoring interrupts Return the number of bytes written or -1...
int pw_uid
Definition: TWinNTSystem.h:50
int DoDirectiveInt(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
Process directive for an integer.
int Poll(int to=-1)
Poll over the read pipe for to secs; return whatever poll returns.
static int AssertBaseDir(const char *path, XrdProofUI ui)
Make sure that the base dir of &#39;path&#39; is either owned by &#39;ui&#39; or gives full permissions to &#39;ui&#39;...
static double p3(double t, double a, double b, double c, double d)
TLine * line
static int GetUserInfo(const char *usr, XrdProofUI &ui)
Get information about user &#39;usr&#39; in a thread safe way.
int gr_gid
Definition: TWinNTSystem.h:62
static const char * AdminMsgType(int type)
Translates the admin message type in a human readable string.
#define s0(x)
Definition: RSha256.hxx:90
static int RmDir(const char *path)
Remove directory at path and its content.
char * gr_name
Definition: TWinNTSystem.h:60
#define XrdSysRecMutex
Definition: XrdSysToOuc.h:18
int DoDirectiveClass(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
Generic class directive processor.
#define TRACE(Flag, Args)
Definition: TGHtml.h:120
int Init(const char *buf)
Init from buffer.
static constexpr double ps
#define XPD_LONGOK(x)
static bool HasToken(const char *s, const char *tokens)
Returns true is &#39;s&#39; contains at least one of the comma-separated tokens in &#39;tokens&#39;.
#define malloc
Definition: civetweb.c:1347
static struct mg_connection * fc(struct mg_context *ctx)
Definition: civetweb.c:3352
int Recv(XpdMsg &msg)
Recv message from the pipe.
static int ParsePidPath(const char *path, XrdOucString &before, XrdOucString &after)
Parse a path in the form of "<before>[.<pid>][.<after>]", filling &#39;rest&#39; and returning &#39;pid&#39;...
static int SymLink(const char *path, const char *link)
Create a symlink &#39;link&#39; to &#39;path&#39; Return 0 in case of success, -1 in case of error.
#define LETTOIDX(x, ilet)
Definition: XrdProofdAux.h:353
static double p2(double t, double a, double b, double c)
void Close()
If open, close and invalidated the pipe descriptors.
char * pw_name
Definition: TWinNTSystem.h:48
bool Matches(const char *s)
Return true if &#39;s&#39; is compatible with this multi-string.
XFontStruct * id
Definition: TGX11.cxx:108
TString flog
Definition: pq2main.cxx:37
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 &#39;fmt&#39;, the up to 5 &#39;const char *&#39;, up to 6 &#39;int&#39; arguments...
XrdOucString fUser
Definition: XrdProofdAux.h:40
#define XPDLOC(d, x)
static const char * ProofRequestTypes(int type)
Translates the proof request type in a human readable string.
SVector< double, 2 > v
Definition: Dict.h:5
static int GetIDFromPath(const char *path, XrdOucString &emsg)
Extract an integer from a file.
int DoDirectiveString(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
Process directive for a string.
auto * a
Definition: textangle.C:12
int changeown(const std::string &path, uid_t u, gid_t g)
Change the ownership of &#39;path&#39; to the entity described by {u,g}.
Definition: proofexecv.cxx:804
#define XrdSysMutexHelper
Definition: XrdSysToOuc.h:17
#define XrdSysError
Definition: XpdSysError.h:8
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 ...
#define XpdBadPGuard(g, u)
Definition: XrdProofdAux.h:368
XrdOucString fGroup
Definition: XrdProofdAux.h:61
#define s1(x)
Definition: RSha256.hxx:91
static double p1(double t, double a, double b)
static long int GetLong(char *str)
Extract first integer from string at &#39;str&#39;, if any.
#define h(i)
Definition: RSha256.hxx:106
static int GetGroupInfo(const char *grp, XrdProofGI &gi)
Get information about group with &#39;gid&#39; in a thread safe way.
PyObject * fType
static int AssertDir(const char *path, XrdProofUI ui, bool changeown)
Make sure that &#39;path&#39; exists and is owned by the entity described by &#39;ui&#39;.
#define d(i)
Definition: RSha256.hxx:102
static int ReadMsg(int fd, XrdOucString &msg)
Receive &#39;msg&#39; from pipe fd.
#define XPDFORM
Definition: XrdProofdAux.h:381
static int CheckIf(XrdOucStream *s, const char *h)
Check existence and match condition of an &#39;if&#39; directive If none (valid) is found, return -1.
#define DIGIT(x)
Definition: XrdProofdAux.h:349
static char * Expand(char *p)
Expand path &#39;p&#39; relative to: $HOME if begins with ~/ <user>&#39;s $HOME if begins with ~<user>/ $PWD if d...
int type
Definition: TGX11.cxx:120
#define SafeFree(x)
Definition: XrdProofdAux.h:341
static int ParseUsrGrp(const char *path, XrdOucString &usr, XrdOucString &grp)
Parse a path in the form of "<usr>[.<grp>][.<pid>]", filling &#39;usr&#39; and &#39;grp&#39;.
#define free
Definition: civetweb.c:1350
static constexpr double s
bool Matches(const char *s)
Return true if &#39;s&#39; is compatible with this token.
static int ChangeMod(const char *path, unsigned int mode)
Change the permission mode of &#39;path&#39; to &#39;mode&#39;.
const char * fHost
Definition: XrdProofdAux.h:114
XrdOucString Export()
Return a string with comma-separated elements.
int pw_gid
Definition: TWinNTSystem.h:51
virtual ~XrdProofdPipe()
Destructor.
XrdOucString fName
Definition: XrdProofdAux.h:111
int Get(int &i)
Get next token and interpret it as an int.
XrdOucString Get(int i)
Return i-th combination (i : 0 -> fN-1)
XrdOucString fHomeDir
Definition: XrdProofdAux.h:42
static int ChangeToDir(const char *dir, XrdProofUI ui, bool changeown)
Change current directory to &#39;dir&#39;.
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
#define snprintf
Definition: civetweb.c:1351
char * pw_dir
Definition: TWinNTSystem.h:54
#define c(i)
Definition: RSha256.hxx:101
static int ChangeOwn(const char *path, XrdProofUI ui)
Change the ownership of &#39;path&#39; to the entity described by &#39;ui&#39;.
int Post(int type, const char *msg)
Post message on the pipe.
void Init(const char *s)
Init the multi-string token.
static int VerifyProcessByID(int pid, const char *pname="proofserv")
Check if a process named &#39;pname&#39; and process &#39;pid&#39; is still in the process table. ...
void Init(const char *s)
Init the multi-string handler.
XrdProofdPipe()
Constructor: create the pipe.
static int GetProcesses(const char *pn, std::map< int, XrdOucString > *plist)
Get from the process table list of PIDs for processes named "proofserv&#39; For {linux, sun, macosx} it uses the system info; for other systems it invokes the command shell &#39;ps ax&#39; via popen.
static void LogEmsgToFile(const char *flog, const char *emsg, const char *pfx=0)
Logs error message &#39;emsg&#39; to file &#39;flog&#39; using standard technology.
XrdOucString Export(int &next)
Export &#39;next&#39; token; use next < 0 start from the first.
int SetHostInDirectives(const char *, XrdProofdDirective *d, void *h)
Set host field for directive &#39;d&#39; to (const char *h)
static constexpr double ns
const Int_t n
Definition: legend1.C:16
static int MvDir(const char *oldpath, const char *newpath)
Move content of directory at oldpath to newpath.
static int KillProcess(int pid, bool forcekill, XrdProofUI ui, bool changeown)
Kill the process &#39;pid&#39;.
char name[80]
Definition: TGX11.cxx:109
#define IDXTOLET(ilet, x)
Definition: XrdProofdAux.h:358
static XrdSysRecMutex fgFormMutex
Definition: XrdProofdAux.h:248