Skip to content
Snippets Groups Projects
Commit c5658762 authored by Fons Rademakers's avatar Fons Rademakers
Browse files

checkin of latest PROOF snapshot. Most changes related to handling of

TFile and TNetFile in local and remote processes.


git-svn-id: http://root.cern.ch/svn/root/trunk@1203 27541ba8-7e3a-0410-8455-c3a389f83636
parent 84715279
No related branches found
No related tags found
No related merge requests found
/* @(#)root/base:$Name: $:$Id: MessageTypes.h,v 1.2 2000/11/21 12:25:38 rdm Exp $ */
/* @(#)root/base:$Name: $:$Id: MessageTypes.h,v 1.3 2000/11/27 10:39:53 rdm Exp $ */
/*************************************************************************
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
......@@ -51,6 +51,8 @@ enum EMessageTypes {
kPROOF_LIMITS, //ask for histogram limits
kPROOF_SENDFILE, //filename, length and file follows
kPROOF_PARALLEL, //number of parallel slaves follows
kPROOF_OPENFILE, //type of file, name and option follows
kPROOF_CLOSEFILE, //name of file follows
//---- ROOTD message opcodes (2000 - 2099)
kROOTD_USER = 2000, //user id follows
......
# PROOF config file. It has a very simple format:
#
# node <hostname> [image=<imagename>]
# slave <hostname> [perf=<perfindex>] [image=<imagename>]
# slave <hostname> [perf=<perfindex>] [image=<imagename>] [port=<portnumber>]
# [user=userid>] [srp]
# user <username> on <hostname>
#
# For each unique node in the cluster add a "node" line.
......@@ -10,11 +11,21 @@
# repeat the slave line N times, where N is the number of CPU's in the machine.
# Perfindex is a number specifying the relative speed of each slave CPU in the
# cluster. Say, the fastest CPU is 100, a CPU 30% slower has perf=70. The
# perfindex is used for load balancing. By default perf=100.
# perfindex is used for load balancing. By default perf=100. The perfindex
# is mostly an indication since the parallel algorithm is adaptive and will
# adjust itself to the current load on each machine.
# Image is used to tell the system that system images are shared between
# nodes/CPU's in the cluster. For example if all nodes share a common user
# directory, like with AFS, set image=afs (<imagename> is arbitrary but should
# be unique for each different image). By default imagename is the hostname.
# Port is used to tell PROOF to connect to the slave servers on the specified
# port (in case proofd was started by the user as opposed to via inetd).
# User is used to tell PROOF to authenticate on the slaves with the specified
# user id. By default the user id used to connect to the master server is
# used. Srp is used to tell PROOF to use SRP (Secure Remote Password) protocol
# to authenticate to the slaves. If this flag is set it is necessary that
# on the master server there is a file ~/.rootnetrc with the needed login
# information and that on the slaves the file ~/.srootdpass exists.
#
# Users can be redirected to have their master server run on a predetermined
# node. For that use the "user" line.
......
// @(#)root/proof:$Name: $:$Id: TProof.h,v 1.4 2000/11/24 18:11:32 rdm Exp $
// @(#)root/proof:$Name: $:$Id: TProof.h,v 1.5 2000/11/27 10:51:46 rdm Exp $
// Author: Fons Rademakers 13/02/97
/*************************************************************************
......@@ -54,6 +54,8 @@ class TProof : public TObject {
friend class TSlave;
private:
enum ESecurity { kNormal, kSRP }; // level of authentication security
TString fMaster; //name of master server (use "" if this is a master)
TString fConfDir; //directory containing cluster config information
TString fConfFile; //file containing config information
......@@ -62,12 +64,13 @@ private:
TString fPasswd; //user password
TString fImage; //master's image name
Int_t fPort; //port we are connected to (proofd = 1093)
Int_t fSecurity; //security level used to connect to master server
Int_t fProtocol; //protocol version number
Int_t fLogLevel; //server debug logging level
Int_t fStatus; //remote return status (part of kPROOF_LOGDONE)
Int_t fParallel; //number of active slaves (only set on client, on server use fActiveSlaves)
Bool_t fMasterServ; //true if we are a master server
Bool_t fSendGroupView; //send new group view
Bool_t fSendGroupView; //if true send new group view
TList *fSlaves; //list of all slave servers as in config file
TList *fActiveSlaves; //list of active slaves (subset of all slaves)
TList *fUniqueSlaves; //list of all active slaves with unique file systems
......@@ -83,7 +86,7 @@ private:
static char *fgUser;
static char *fgPasswd;
Int_t Init(const char *master, Int_t port, const char *conffile,
Int_t Init(const char *masterurl, const char *conffile,
const char *confdir, Int_t loglevel);
Int_t Collect(TMonitor *mon);
void ConnectFiles();
......@@ -105,8 +108,7 @@ public:
enum ESlaves { kAll, kActive, kUnique };
enum EUrgent { kHardInterrupt = 1, kSoftInterrupt, kShutdownInterrupt };
TProof(const char *master, Int_t port = kPROOF_Port,
const char *conffile = kPROOF_ConfFile,
TProof(const char *masterurl, const char *conffile = kPROOF_ConfFile,
const char *confdir = kPROOF_ConfDir, Int_t loglevel = 1);
virtual ~TProof();
......
// @(#)root/proof:$Name: $:$Id: TSlave.h,v 1.1.1.1 2000/05/16 17:00:46 rdm Exp $
// @(#)root/proof:$Name: $:$Id: TSlave.h,v 1.2 2000/11/21 12:27:59 rdm Exp $
// Author: Fons Rademakers 14/02/97
/*************************************************************************
......@@ -43,9 +43,11 @@ private:
TString fName; //slave's hostname
TString fImage; //slave's image name
TString fWorkDir; //slave's working directory (info obtained from slave)
TString fUser; //slave's user id
Int_t fPort; //slave's port number
Int_t fOrdinal; //slave's ordinal number
Int_t fPerfIdx; //relative CPU performance index
Int_t fSecurity; //authentication method (0 = standard, 1 = SRP)
TSocket *fSocket; //socket to slave
TProof *fProof; //proof cluster to which slave belongs
TFileHandler *fInput; //input handler related to this slave
......@@ -58,7 +60,7 @@ private:
void operator=(const TSlave &) { }
TSlave(const char *host, Int_t port, Int_t ord, Int_t perf,
const char *image, TProof *proof);
const char *image, const char *user, Int_t security, TProof *proof);
public:
virtual ~TSlave();
......@@ -71,6 +73,7 @@ public:
const char *GetName() const { return fName.Data(); }
const char *GetImage() const { return fImage.Data(); }
const char *GetWorkingDirectory() const { return fWorkDir.Data(); }
const char *GetUser() const { return fUser.Data(); }
Int_t GetPort() const { return fPort; }
Int_t GetOrdinal() const { return fOrdinal; }
Int_t GetPerfIdx() const { return fPerfIdx; }
......
// @(#)root/proof:$Name: $:$Id: TProof.cxx,v 1.5 2000/11/27 10:51:46 rdm Exp $
// @(#)root/proof:$Name: $:$Id: TProof.cxx,v 1.6 2000/11/27 18:37:12 rdm Exp $
// Author: Fons Rademakers 13/02/97
/*************************************************************************
......@@ -38,6 +38,7 @@
#include "TMessage.h"
#include "TSystem.h"
#include "TError.h"
#include "TUrl.h"
#include "TROOT.h"
#include "TFile.h"
#include "TTree.h"
......@@ -72,12 +73,18 @@ Bool_t TProofInputHandler::Notify()
ClassImp(TProof)
//______________________________________________________________________________
TProof::TProof(const char *master, Int_t port, const char *conffile,
TProof::TProof(const char *masterurl, const char *conffile,
const char *confdir, Int_t loglevel)
{
// Create a PROOF environment. Starting PROOF involves reading a config
// file describing the cluster and firing slave servers on all of the
// available nodes.
// Create a PROOF environment. Starting PROOF involves either connecting
// to a master server, which in turn will start a set of slave servers, or
// directly starting as master server (if master = ""). Masterurl is of
// the form: proof://host[:port] or proofs://host[:port]. Conffile is
// the name of the config file describing the remote PROOF cluster
// (this argument alows you to describe different cluster configurations).
// The default proof.conf. Confdir is the directory where the config
// file and other PROOF related files are (like motd and noproof files).
// Loglevel is the og level (default = 1).
// Can have only one PROOF session open at a time.
if (gProof) {
......@@ -85,7 +92,7 @@ TProof::TProof(const char *master, Int_t port, const char *conffile,
gProof->Close();
}
if (Init(master, port, conffile, confdir, loglevel) == 0) {
if (Init(masterurl, conffile, confdir, loglevel) == 0) {
// on Init failure make sure IsValid() returns kFALSE
SafeDelete(fActiveSlaves);
}
......@@ -111,29 +118,41 @@ TProof::~TProof()
}
//______________________________________________________________________________
Int_t TProof::Init(const char *master, Int_t port, const char *conffile,
Int_t TProof::Init(const char *masterurl, const char *conffile,
const char *confdir, Int_t loglevel)
{
// Start the PROOF environment. Starting PROOF involves either connecting
// to a master server, which in turn will start a set of slave servers, or
// directly starting as master server (if master = "").
// directly starting as master server (if master = ""). For a description
// of the arguments see the TProof ctor.
Assert(gSystem);
fMaster = master;
fPort = port;
TUrl *u;
if (!masterurl || !*masterurl)
u = new TUrl("proof://__master__");
else if (strstr(masterurl, "://"))
u = new TUrl(masterurl);
else
u = new TUrl(Form("proof://%s", masterurl));
fMaster = u->GetHost();
fPort = u->GetPort();
fSecurity = !strcmp(u->GetProtocol(), "proofs") ? kSRP : kNormal;
fConfDir = confdir;
fConfFile = conffile;
fWorkDir = gSystem->WorkingDirectory();
fLogLevel = loglevel;
fProtocol = kPROOF_Protocol;
fMasterServ = fMaster == "" ? kTRUE : kFALSE;
fMasterServ = fMaster == "__master__" ? kTRUE : kFALSE;
fSendGroupView = kTRUE;
fImage = "";
fStatus = 0;
fParallel = 0;
fTree = 0;
delete u;
// sort slaves by descending performance index
fSlaves = new TSortedList(kSortDescending);
fActiveSlaves = new TList;
......@@ -149,17 +168,16 @@ Int_t TProof::Init(const char *master, Int_t port, const char *conffile,
if (IsMaster()) {
char fconf[256];
sprintf(fconf, ".%s", conffile);
sprintf(fconf, "%s/.%s", gSystem->Getenv("HOME"), conffile);
if (gSystem->AccessPathName(fconf, kFileExists)) {
sprintf(fconf, "%s/.%s", gSystem->Getenv("HOME"), conffile);
sprintf(fconf, "%s/proof/etc/%s", confdir, conffile);
if (gSystem->AccessPathName(fconf, kFileExists)) {
sprintf(fconf, "%s/proof/etc/%s", confdir, conffile);
if (gSystem->AccessPathName(fconf, kFileExists)) {
Error("Init", "no PROOF config file found");
return 0;
}
Error("Init", "no PROOF config file found");
return 0;
}
}
if (gDebug > 1)
Printf("Using PROOF config file: %s", fconf);
FILE *pconf;
if ((pconf = fopen(fconf, "r"))) {
......@@ -172,10 +190,10 @@ Int_t TProof::Init(const char *master, Int_t port, const char *conffile,
int ord = 0;
while (fgets(line, sizeof(line), pconf)) {
char word[4][64];
char word[7][64];
if (line[0] == '#') continue; // skip comment lines
int nword = sscanf(line, " %s %s %s %s", word[0], word[1], word[2],
word[3]);
int nword = sscanf(line, "%s %s %s %s %s %s %s", word[0], word[1],
word[2], word[3], word[4], word[5], word[6]);
// find node on which master runs
if (nword >= 2 && !strcmp(word[0], "node") && !fImage.Length()) {
......@@ -190,16 +208,26 @@ Int_t TProof::Init(const char *master, Int_t port, const char *conffile,
}
// find all slave servers
if (nword >= 2 && !strcmp(word[0], "slave")) {
int perfidx = 100;
char *image = word[1];
int perfidx = 100;
int sport = fPort;
int security = kNormal;
const char *image = word[1];
const char *user = fUser.Data();
for (int i = 2; i < nword; i++) {
if (!strncmp(word[i], "perf=", 5))
perfidx = atoi(word[i]+5);
if (!strncmp(word[i], "image=", 6))
image = word[i]+6;
if (!strncmp(word[i], "port=", 5))
sport = atoi(word[i]+5);
if (!strncmp(word[i], "user=", 5))
user = word[i]+5;
if (!strncmp(word[i], "srp", 3))
security = kSRP;
}
// create slave server
TSlave *slave = new TSlave(word[1], port, ord++, perfidx, image, this);
TSlave *slave = new TSlave(word[1], sport, ord++, perfidx,
image, user, security, this);
fSlaves->Add(slave);
if (slave->IsValid()) {
fAllMonitor->Add(slave->GetSocket());
......@@ -218,7 +246,8 @@ Int_t TProof::Init(const char *master, Int_t port, const char *conffile,
}
} else {
// create master server
TSlave *slave = new TSlave(fMaster, port, 0, 100, "master", this);
TSlave *slave = new TSlave(fMaster, fPort, 0, 100, "master", fUser,
fSecurity, this);
fSlaves->Add(slave);
if (slave->IsValid()) {
fAllMonitor->Add(slave->GetSocket());
......@@ -253,17 +282,23 @@ Int_t TProof::Init(const char *master, Int_t port, const char *conffile,
Int_t TProof::ConnectFile(const TFile *file)
{
// Send message to all slaves to connect "file". This method is
// called by the TFile ctor (no user method).
// called by the TFile ctor (no user method). Message is only send
// if file was opened in READ mode.
if (!IsValid() || !file) return 0;
TString clsnam = file->IsA()->GetName();
TString filenam = file->GetName();
TString option = file->GetOption();
// only propagate files opened in READ mode to PROOF servers
if (option.CompareTo("READ", TString::kIgnoreCase))
return 0;
// A TFile can only be opened on all machines if the master and slaves
// share the same file system image.
if (clsnam == "TFile") {
if (GetNumberOfUniqueSlaves() != 0)
if (GetNumberOfUniqueSlaves() > 0)
return 0;
else {
if (!gSystem->IsAbsoluteFileName(filenam)) {
......@@ -274,8 +309,10 @@ Int_t TProof::ConnectFile(const TFile *file)
}
}
return SendCommand(Form("new %s(\"%s\", \"%s\");", clsnam.Data(),
filenam.Data(), file->GetOption()), kAll);
TMessage mess(kPROOF_OPENFILE);
mess << clsnam << filenam << option;
Broadcast(mess, kAll);
return Collect(kAll);
}
//______________________________________________________________________________
......@@ -349,7 +386,7 @@ void TProof::FindUniqueSlaves()
TSlave *sl;
while ((sl = (TSlave *)next())) {
if (fImage == sl->fImage && fWorkDir == sl->fWorkDir) continue;
if (fImage == sl->fImage) continue;
TIter next2(fUniqueSlaves);
TSlave *sl2;
Int_t add = fUniqueSlaves->IsEmpty() ? 1 : 0;
......@@ -1116,7 +1153,8 @@ Int_t TProof::Exec(const char *cmd, ESlaves list)
// Send command to be executed on the PROOF master and/or slaves.
// Command can be any legal command line command. Commands like
// ".x file.C" or ".L file.C" will cause the file file.C to be send
// to the PROOF cluster.
// to the PROOF cluster. Returns -1 in case of error, >=0 in case of
// succes.
if (!IsValid()) return 0;
......@@ -1132,10 +1170,21 @@ Int_t TProof::Exec(const char *cmd, ESlaves list)
file = file.Strip(TString::kTrailing, '+');
char *fn = gSystem->Which(TROOT::GetMacroPath(), file, kReadPermission);
if (fn) {
if (SendFile(fn, kFALSE, kUnique) < 0) {
Error("Exec", "file %s could not be transfered to PROOF", fn);
return 0;
if (GetNumberOfUniqueSlaves() > 0) {
if (SendFile(fn, kFALSE, kUnique) < 0) {
Error("Exec", "file %s could not be transfered to PROOF", fn);
delete [] fn;
return -1;
}
} else {
TString scmd = s(0,3) + fn;
Int_t n = SendCommand(scmd);
delete [] fn;
return n;
}
} else {
Error("Exec", "macro %s not found", file.Data());
return -1;
}
delete [] fn;
}
......@@ -1149,7 +1198,7 @@ Int_t TProof::SendCommand(const char *cmd, ESlaves list)
// Send command to be executed on the PROOF master and/or slaves.
// Command can be any legal command line command, however commands
// like ".x file.C" or ".L file.C" will not cause the file.C to be
// transfered to the PROOF cluter. In that case use TProof::Exec().
// transfered to the PROOF cluster. In that case use TProof::Exec().
// Returns the status send by the remote server as part of the
// kPROOF_LOGDONE message. Typically this is the return code of the
// command on the remote side.
......@@ -1197,9 +1246,10 @@ Int_t TProof::SendInitialState()
//______________________________________________________________________________
Int_t TProof::SendFile(const char *file, Bool_t bin, ESlaves list)
{
// Send an ascii file to master or slave servers. Returns number of slaves
// Send a file to master or slave servers. Returns number of slaves
// the file was sent to, maybe 0 in case master and slaves have the same
// file system image, -1 in case of error.
// file system image, -1 in case of error. If bin is true binary
// file transfer is used, otherwise ASCII mode.
TList *slaves = 0;
if (list == kAll) slaves = fSlaves;
......
// @(#)root/proof:$Name: $:$Id: TProofServ.cxx,v 1.6 2000/11/27 10:51:46 rdm Exp $
// @(#)root/proof:$Name: $:$Id: TProofServ.cxx,v 1.7 2000/11/27 18:37:12 rdm Exp $
// Author: Fons Rademakers 16/02/97
/*************************************************************************
......@@ -34,12 +34,14 @@ typedef long off_t;
#include "TROOT.h"
#include "TFile.h"
#include "TSysEvtHandler.h"
#include "TAuthenticate.h"
#include "TSystem.h"
#include "TInterpreter.h"
#include "TException.h"
#include "TSocket.h"
#include "TStopwatch.h"
#include "TMessage.h"
#include "TUrl.h"
#include "TEnv.h"
#include "TError.h"
#include "TTree.h"
......@@ -221,7 +223,7 @@ TProofServ::TProofServ(int *argc, char **argv)
if (IsMaster()) {
TProof::SetUser(fUser);
TProof::SetPasswd(fUserPass);
new TProof("", kPROOF_Port, fConfFile, fConfDir, fLogLevel);
new TProof("", fConfFile, fConfDir, fLogLevel);
SendLogFile();
}
}
......@@ -484,6 +486,34 @@ void TProofServ::HandleSocketInput()
}
break;
case kPROOF_OPENFILE:
{
// open file on master, if successfull this will also send the
// connect message to the slaves
TString clsnam, filenam, option;
(*mess) >> clsnam >> filenam >> option;
TString cmd;
cmd = "TFile::Open(\"" + filenam + "\", \"" + option + "\");";
if (IsMaster()) {
if (clsnam == "TNetFile") {
TUrl url(filenam);
TAuthenticate auth(0, url.GetProtocol(), url.GetHost());
char *user, *passwd;
if (auth.CheckNetrc(user, passwd)) {
ProcessLine(cmd);
delete [] user;
delete [] passwd;
} else
Error("HandleSocketInput", "cannot execute \"%s\" since authentication is not possible",
cmd.Data());
} else
ProcessLine(cmd);
} else
ProcessLine(cmd);
}
SendLogFile();
break;
case kPROOF_PARALLEL:
if (IsMaster()) {
Int_t nodes;
......
// @(#)root/proof:$Name: $:$Id: TSlave.cxx,v 1.3 2000/11/21 12:27:59 rdm Exp $
// @(#)root/proof:$Name: $:$Id: TSlave.cxx,v 1.4 2000/11/24 18:11:32 rdm Exp $
// Author: Fons Rademakers 14/02/97
/*************************************************************************
......@@ -30,19 +30,22 @@ ClassImp(TSlave)
//______________________________________________________________________________
TSlave::TSlave(const char *host, Int_t port, Int_t ord, Int_t perf,
const char *image, TProof *proof)
const char *image, const char *user, Int_t security,
TProof *proof)
{
// Create a PROOF slave object. Called via the TProof ctor.
fName = host;
fPort = port;
fImage = image;
fWorkDir = kPROOF_WorkDir;
fOrdinal = ord;
fPerfIdx = perf;
fProof = proof;
fSocket = 0;
fInput = 0;
fName = host;
fPort = port;
fImage = image;
fWorkDir = kPROOF_WorkDir;
fUser = user;
fOrdinal = ord;
fPerfIdx = perf;
fSecurity = security;
fProof = proof;
fSocket = 0;
fInput = 0;
// Open connection to remote PROOF slave server.
fSocket = new TSocket(host, port);
......@@ -140,6 +143,7 @@ void TSlave::Print(Option_t *)
Printf("*** Slave %d (%s)", fOrdinal, fSocket ? "valid" : "invalid");
Printf(" Host name: %s", GetName());
Printf(" Port number: %d", GetPort());
Printf(" User: %s", GetUser());
Printf(" Image name: %s", GetImage());
Printf(" Working directory: %s", GetWorkingDirectory());
Printf(" Performance index: %d", GetPerfIdx());
......
// @(#)root/proofd:$Name: $:$Id: proofd.cxx,v 1.10 2000/11/24 18:11:32 rdm Exp $
// @(#)root/proofd:$Name: $:$Id: proofd.cxx,v 1.11 2000/12/01 14:22:26 rdm Exp $
// Author: Fons Rademakers 02/02/97
/*************************************************************************
......@@ -13,14 +13,58 @@
// //
// Proofd //
// //
// Proof, Parallel ROOT Facility, front-end daemon. //
// This small server is started by inetd when a client requests //
// a connection to a Proof server. If we don't want the Proof server //
// PROOF, Parallel ROOT Facility, front-end daemon. //
// This small server is started either by inetd when a client requests //
// a connection to a PROOF server or by hand (i.e. from the command //
// line). By default proofd uses port 1093 (allocated by IANA, //
// www.iana.org, to proofd). If we don't want the PROOF server //
// to run on this specific node, e.g. because the system is being //
// shutdown or there are already too many servers running, we send //
// the client a re-route message and close the connection. Otherwise //
// we receive the client's version key and exec the appropriate //
// server version. //
// we authenticate the user and exec the proofserv program. //
// To run proofd via inetd add the following line to /etc/services: //
// //
// proofd 1093/tcp //
// //
// and to /etc/inetd.conf: //
// //
// proofd stream tcp nowait root /usr/local/root/bin/proofd -i \ //
// /usr/local/root //
// //
// Force inetd to reread its conf file with "kill -HUP <pid inetd>". //
// You can also start proofd by hand running directly under your //
// private account (no root system priviliges needed). For example to //
// start proofd listening on port 5252 just type: //
// //
// prootf -p 5252 $ROOTSYS //
// //
// Notice: no & is needed. Proofd will go in background by itself. //
// //
// Proofd arguments: //
// -i says we were started by inetd //
// -p port# specifies a different port to listen on //
// rootsys_dir directory which must contain bin/proofserv and //
// proof/etc/proof.conf //
// //
// When your system uses shadow passwords you have to compile proofd //
// with -DR__SHADOWPW. Since shadow passwords can only be accessed //
// while being superuser (root) this works only when the server is //
// started via inetd. Another solution is to create a file //
// ~/.rootdpass containing an encrypted password. If this file exists //
// its password is used for authentication. This method overrides //
// all other authentication methods. To create an encrypted password //
// do something like: //
// perl -e '$pw = crypt("<secretpasswd>","salt"); print "$pw\n"' //
// and store this string in ~/.rootdpass. //
// //
// To use AFS for authentication compile proofd with the -DR__AFS //
// flag. In that case you also need to link with the AFS libraries. //
// See the Makefiles for more details. //
// //
// To use Secure Remote Passwords (SRP) for authentication compile //
// proofd with the -DR__SRP flag. In that case you also need to link //
// with the SRP and gmp libraries. See the Makefile for more details. //
// SRP is described at: http://srp.stanford.edu/. //
// //
//////////////////////////////////////////////////////////////////////////
......@@ -120,7 +164,7 @@ static int setresuid(uid_t r, uid_t e, uid_t)
#endif
void Send(char *msg)
void Send(const char *msg)
{
// Simulate TSocket::Send(const char *str).
......@@ -152,7 +196,7 @@ int Recv(char *msg, int max)
return hlen;
}
void fatal_error(char *msg)
void fatal_error(const char *msg)
{
Send(msg);
exit(1);
......@@ -237,7 +281,7 @@ char *check_pass()
return user_name;
}
char *reroute_user(char *confdir, char *user_name)
char *reroute_user(const char *confdir, const char *user_name)
{
// Look if user should be rerouted to another server node.
......@@ -320,6 +364,7 @@ char *reroute_user(char *confdir, char *user_name)
return 0;
}
//______________________________________________________________________________
int main(int /* argc */, char **argv)
{
// Arguments: <confdir>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment