00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00031
00032
00033 int XrdRootdProtocol::Count = 0;
00034
00035 const char *XrdRootdProtocol::TraceID = "Rootd: ";
00036
00037
00038
00039
00040
00041 #define MAX_ARGS 128
00042
00043
00044
00045
00046
00047
00048
00049
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
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
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
00083
00084 fn = pc-1;
00085 while(*fn != '/' && fn != pgm) fn--;
00086 parg[0] = strdup(++fn);
00087
00088
00089
00090
00091
00092 parg[1] = strdup("-i");
00093
00094
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
00105
00106
00107 if (*pc)
00108 {pi->eDest->Say("rootd: Too many arguments to program ", pgm);
00109 return (XrdProtocol *)0;
00110 }
00111
00112
00113
00114 parg[acnt++] = 0;
00115 pap = (char **)malloc(acnt*sizeof(char *));
00116 memcpy((void *)pap, (const void *)parg, acnt*sizeof(char *));
00117
00118
00119
00120 pi->eDest->Say(0, "rootd protocol interface V 1.1 successfully loaded.");
00121
00122
00123
00124 return (XrdProtocol *)new XrdRootdProtocol(pi,strdup(pgm),(const char **)pap);
00125 }
00126 }
00127
00128
00129
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
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
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
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
00177
00178 TRACEI(PROT, "executing " <<Program);
00179
00180
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
00189
00190 dup2(stderrFD, STDERR_FILENO);
00191 close(stderrFD);
00192
00193
00194
00195
00196 dup2(lp->FDnum(), STDIN_FILENO);
00197 dup2(lp->FDnum(), STDOUT_FILENO);
00198
00199
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
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
00216
00217 if (!buff) return sizeof(statfmt)+16;
00218
00219
00220
00221 return snprintf(buff, blen, statfmt, Count);
00222 }