XrdRootdProtocol.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                   X r d R o o t d P r o t o c o l . c c                    */
00004 /*                                                                            */
00005 /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*       All Rights Reserved. See XrdInfo.cc for complete License Terms       */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC03-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //       $Id: XrdRootdProtocol.cc 22437 2008-03-04 14:35:16Z rdm $ 
00012 
00013 const char *XrdRootdProtocolCVSID = "$Id: XrdRootdProtocol.cc 22437 2008-03-04 14:35:16Z rdm $";
00014 
00015 #include <stdio.h>
00016 #include <string.h>
00017 #include <unistd.h>
00018 #include <sys/types.h>
00019 #include <netinet/in.h>
00020 
00021 #include "XrdSys/XrdSysError.hh"
00022 #include "XrdRootd/XrdRootdProtocol.hh"
00023 #include "Xrd/XrdLink.hh"
00024 #include "Xrd/XrdScheduler.hh"
00025 #undef   XRD_TRACE
00026 #define  XRD_TRACE XrdTrace->
00027 #include "Xrd/XrdTrace.hh"
00028 
00029 /******************************************************************************/
00030 /*                               G l o b a l s                                */
00031 /******************************************************************************/
00032   
00033       int   XrdRootdProtocol::Count = 0;
00034 
00035 const char *XrdRootdProtocol::TraceID = "Rootd: ";
00036 
00037 /******************************************************************************/
00038 /*                         L o c a l   D e f i n e s                          */
00039 /******************************************************************************/
00040   
00041 #define MAX_ARGS 128
00042 
00043 /******************************************************************************/
00044 /*                       P r o t o c o l   L o a d e r                        */
00045 /******************************************************************************/
00046   
00047 // This protocol is meant to live in a shared library. The interface below is
00048 // used by the server to obtain a copy of the protocol object that can be used
00049 // to decide whether or not a link is talking a particular protocol.
00050 //
00051 extern "C"
00052 {
00053 XrdProtocol *XrdgetProtocol(const char *pname, char *parms,
00054                      XrdProtocol_Config *pi)
00055 {
00056    char *pc, *pgm, *fn;
00057    int acnt = 0;
00058    char *parg[MAX_ARGS], **pap;
00059 
00060 // If a command is available, then this protocol can be used
00061 //
00062    if (!(pc = parms))
00063       {pi->eDest->Say(0,"rootd: Protocol handler command not specified");
00064        return (XrdProtocol *)0;
00065       }
00066    if (*pc != '/')
00067       {pi->eDest->Say(0,"rootd: Protocol handler command is not absolute");
00068        return (XrdProtocol *)0;
00069       }
00070 
00071 // Make sure the command is actually an executable program
00072 //
00073    while(*pc && *pc == ' ') pc++;
00074    pgm = pc;
00075    while(*pc && *pc != ' ') pc++;
00076    if (*pc) {*pc = '\0'; pc++;}
00077    if (access(pgm, F_OK) || access(pgm, X_OK))
00078       {pi->eDest->Emsg("rootd" ,errno, "find rootd program", pgm);
00079        return (XrdProtocol *)0;
00080       }
00081 
00082 // Establish the first argument (filename)
00083 //
00084    fn = pc-1;
00085    while(*fn != '/' && fn != pgm) fn--;
00086    parg[0] = strdup(++fn);
00087 
00088 // Force first argument to the program be '-i', so the user does not
00089 // need to specify it in the config file; and if it does, the second
00090 // instance will be ignored
00091 //
00092    parg[1] = strdup("-i");
00093 
00094 // Tokenize the remaining arguments (we do not support quotes)
00095 //
00096    for (acnt = 2; acnt < MAX_ARGS-1 && *pc; acnt++)
00097        {while(*pc && *pc == ' ') pc++;
00098         parg[acnt] = pc;
00099         while(*pc && *pc != ' ') pc++;
00100         if (*pc) {*pc = '\0'; pc++;}
00101         parg[acnt] = strdup(parg[acnt]);
00102        }
00103 
00104 // Check if we execeeded the arg count (yeah, we leak if an error occurs but
00105 // this program will be shortly terminated if we do).
00106 //
00107    if (*pc)
00108       {pi->eDest->Say("rootd: Too many arguments to program ", pgm);
00109        return (XrdProtocol *)0;
00110       }
00111 
00112 // Copy the arglist
00113 //
00114    parg[acnt++] = 0;
00115    pap = (char **)malloc(acnt*sizeof(char *));
00116    memcpy((void *)pap, (const void *)parg, acnt*sizeof(char *));
00117 
00118 // Issue herald
00119 //
00120   pi->eDest->Say(0, "rootd protocol interface V 1.1 successfully loaded.");
00121 
00122 // Return the protocol object to be used
00123 //
00124    return (XrdProtocol *)new XrdRootdProtocol(pi,strdup(pgm),(const char **)pap);
00125 }
00126 }
00127 
00128 /******************************************************************************/
00129 /*                           C o n s t r u c t o r                            */
00130 /******************************************************************************/
00131 
00132 XrdRootdProtocol::XrdRootdProtocol(XrdProtocol_Config *pi,
00133                                const char *pgm, const char **pap) :
00134                                XrdProtocol("rootd protocol")
00135 {
00136     Program   = pgm;
00137     ProgArg   = pap;
00138 
00139     eDest     = pi->eDest;
00140     Scheduler = pi->Sched;
00141     XrdTrace = pi->Trace;
00142     stderrFD  = eDest->baseFD();
00143     ReadWait  = pi->readWait;
00144 }
00145 
00146 /******************************************************************************/
00147 /*                                 M a t c h                                  */
00148 /******************************************************************************/
00149 
00150 #define TRACELINK lp
00151   
00152 XrdProtocol *XrdRootdProtocol::Match(XrdLink *lp)
00153 {
00154      struct handshake
00155            {int eight;
00156            } hsdata;
00157 
00158      char  *hsbuff = (char *)&hsdata;
00159      pid_t pid;
00160      int  dlen;
00161 
00162 // Peek at the first 4 bytes of data
00163 //
00164    if ((dlen = lp->Peek(hsbuff, sizeof(hsdata), ReadWait)) != sizeof(hsdata))
00165       {lp->setEtext("rootd handshake not received");
00166        return (XrdProtocol *)0;
00167       }
00168 
00169 // Verify that this is our protocol
00170 //
00171    hsdata.eight = ntohl(hsdata.eight);
00172    if (dlen != sizeof(hsdata) || hsdata.eight != 8) return (XrdProtocol *)0;
00173    Count++;
00174    TRACEI(PROT, "Matched rootd protocol on link");
00175 
00176 // Trace this now since we won't be able to do much after the fork()
00177 //
00178    TRACEI(PROT, "executing " <<Program);
00179 
00180 // Fork a process to handle this protocol
00181 //
00182    if ((pid = Scheduler->Fork(lp->Name())))
00183       {if (pid < 0) lp->setEtext("rootd fork failed");
00184           else lp->setEtext("link transfered");
00185        return (XrdProtocol *)0;
00186       }
00187 
00188 // Restablish standard error for the program we will exec
00189 //
00190    dup2(stderrFD, STDERR_FILENO);
00191    close(stderrFD);
00192 
00193 // Force stdin/out to point to the socket FD (this will also bypass the
00194 // close on exec setting for the socket)
00195 //
00196    dup2(lp->FDnum(), STDIN_FILENO);
00197    dup2(lp->FDnum(), STDOUT_FILENO);
00198 
00199 // Do the exec
00200 //
00201    execv((const char *)Program, (char * const *)ProgArg);
00202    cerr <<"Xrdrootd: Oops! Exec(" <<Program <<") failed; errno=" <<errno <<endl;
00203    _exit(17);
00204 }
00205  
00206 /******************************************************************************/
00207 /*                                 S t a t s                                  */
00208 /******************************************************************************/
00209   
00210 int XrdRootdProtocol::Stats(char *buff, int blen, int do_sync)
00211 {
00212 
00213    static char statfmt[] = "<stats id=\"rootd\"><num>%ld</num></stats>";
00214 
00215 // If caller wants only size, give it to him
00216 //
00217    if (!buff) return sizeof(statfmt)+16;
00218 
00219 // We have only one statistic -- number of successful matches, ignore do_sync
00220 //
00221    return snprintf(buff, blen, statfmt, Count);
00222 }

Generated on Tue Jul 5 14:46:57 2011 for ROOT_528-00b_version by  doxygen 1.5.1