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