00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdOucProgCVSID = "$Id: XrdOucProg.cc 32231 2010-02-05 18:24:46Z ganis $";
00014
00015 #include <errno.h>
00016 #include <stdio.h>
00017 #include <string.h>
00018 #ifndef WIN32
00019 #include <unistd.h>
00020 #include <sys/types.h>
00021 #include <sys/wait.h>
00022 #else
00023 #include <sys/types.h>
00024 #include "XrdSys/XrdWin32.hh"
00025 #endif
00026
00027 #include "XrdOuc/XrdOucProg.hh"
00028 #include "XrdOuc/XrdOucStream.hh"
00029 #include "XrdSys/XrdSysError.hh"
00030 #include "XrdSys/XrdSysPthread.hh"
00031
00032
00033
00034
00035
00036 XrdOucProg::~XrdOucProg()
00037 {
00038 if (ArgBuff) free(ArgBuff);
00039 if (myStream) delete myStream;
00040 }
00041
00042
00043
00044
00045
00046 int XrdOucProg::Feed(const char *data[], const int dlen[])
00047 {
00048 static XrdSysMutex feedMutex;
00049 XrdSysMutexHelper feedHelper;
00050 int rc;
00051
00052
00053
00054 if (!myStream) return EPIPE;
00055 feedHelper.Lock(&feedMutex);
00056
00057
00058
00059 if (!myStream->isAlive() && !Restart())
00060 {if (eDest) eDest->Emsg("Prog" "Unable to restart", Arg[0]);
00061 return EPIPE;
00062 }
00063
00064
00065
00066 if (!myStream->Put((const char **)data, (const int *)dlen)) return 0;
00067 if (eDest)
00068 eDest->Emsg("Prog", myStream->LastError(), "feed", Arg[0]);
00069 if ((rc = Restart()))
00070 {if (eDest) eDest->Emsg("Prog", rc, "restart", Arg[0]);
00071 return EPIPE;
00072 }
00073 if (!myStream->Put((const char **)data, (const int *)dlen)) return 0;
00074 if (eDest)
00075 eDest->Emsg("Prog", myStream->LastError(), "refeed", Arg[0]);
00076 return EPIPE;
00077 }
00078
00079
00080
00081
00082
00083 int XrdOucProg::Run(XrdOucStream *Sp, const char *arg1, const char *arg2,
00084 const char *arg3, const char *arg4)
00085 {
00086 const int maxArgs = sizeof(Arg)/sizeof(Arg[0])+4;
00087 char *myArgs[maxArgs+1];
00088 int rc, j = numArgs;
00089
00090
00091
00092 if (!ArgBuff)
00093 {if (eDest) eDest->Emsg("Run", "No program specified");
00094 return -ENOEXEC;
00095 }
00096
00097
00098
00099 memcpy((void *)myArgs, (const void *)Arg, lenArgs);
00100
00101
00102
00103 if (arg1 && j < maxArgs) myArgs[j++] = (char *)arg1;
00104 if (arg2 && j < maxArgs) myArgs[j++] = (char *)arg2;
00105 if (arg3 && j < maxArgs) myArgs[j++] = (char *)arg3;
00106 if (arg4 && j < maxArgs) myArgs[j++] = (char *)arg4;
00107
00108
00109
00110 if (j >= maxArgs)
00111 {if (eDest) eDest->Emsg("Run", E2BIG, "execute", Arg[0]);
00112 return -E2BIG;
00113 }
00114 myArgs[j] = (char *)0;
00115
00116
00117
00118 if (Sp->Exec(myArgs, 1, theEFD))
00119 {rc = Sp->LastError();
00120 if (eDest) eDest->Emsg("Run", rc, "execute", Arg[0]);
00121 return -rc;
00122 }
00123
00124
00125
00126 return 0;
00127 }
00128
00129
00130
00131 int XrdOucProg::Run(const char *arg1, const char *arg2,
00132 const char *arg3, const char *arg4)
00133 {
00134 XrdOucStream cmd;
00135 char *lp;
00136 int rc;
00137
00138
00139
00140 if ((rc = Run(&cmd, arg1, arg2, arg3, arg4))) return rc;
00141
00142
00143
00144 while((lp = cmd.GetLine()))
00145 if (eDest && *lp) eDest->Emsg("Run", lp);
00146
00147
00148
00149 rc = cmd.Drain();
00150
00151
00152
00153 if (WIFSIGNALED(rc))
00154 {if (eDest)
00155 {char buff[16];
00156 sprintf(buff, "%d", WTERMSIG(rc));
00157 eDest->Emsg("Run", Arg[0], "killed by signal", buff);
00158 }
00159 return -EPIPE;
00160 }
00161 if (WIFEXITED(rc))
00162 {rc = WEXITSTATUS(rc);
00163 if (rc && eDest)
00164 {char buff[16];
00165 sprintf(buff, "%d", rc);
00166 eDest->Emsg("Run", Arg[0], "ended with status", buff);
00167 }
00168 return -rc;
00169 }
00170 return 0;
00171 }
00172
00173
00174
00175
00176
00177 int XrdOucProg::Setup(const char *prog, XrdSysError *errP)
00178 {
00179 const int maxArgs = sizeof(Arg)/sizeof(Arg[0]);
00180 char *pp;
00181 int j;
00182
00183
00184
00185 if (ArgBuff) free(ArgBuff);
00186 pp = ArgBuff = strdup(prog);
00187 if (!errP) errP = eDest;
00188
00189
00190
00191 for (j = 0; j < maxArgs-1 && *pp; j++)
00192 {while(*pp == ' ') pp++;
00193 if (!(*pp)) break;
00194 Arg[j] = pp;
00195 while(*pp && *pp != ' ') pp++;
00196 if (*pp) {*pp = '\0'; pp++;}
00197 }
00198
00199
00200
00201 if (j == maxArgs-1 && *pp)
00202 {if (errP) errP->Emsg("Run", E2BIG, "set up", Arg[0]);
00203 free(ArgBuff); ArgBuff = 0;
00204 return -E2BIG;
00205 }
00206 Arg[j] = (char *)0;
00207 numArgs= j;
00208 lenArgs = sizeof(Arg[0]) * numArgs;
00209
00210
00211
00212 if (access(Arg[0], X_OK))
00213 {int rc = errno;
00214 if (errP) errP->Emsg("Run", rc, "set up", Arg[0]);
00215 free(ArgBuff); ArgBuff = 0;
00216 return rc;
00217 }
00218 return 0;
00219 }
00220
00221
00222
00223
00224
00225 int XrdOucProg::Start()
00226 {
00227
00228
00229
00230 if (myStream) return EBUSY;
00231 if (!(myStream = new XrdOucStream(eDest))) return ENOMEM;
00232
00233
00234
00235 theEFD = 0;
00236 return Run(myStream);
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246 int XrdOucProg::Restart()
00247 {
00248 myStream->Close();
00249 return Run(myStream);
00250 }