XRootD
Loading...
Searching...
No Matches
XrdOucProg.cc File Reference
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "XrdOuc/XrdOucEnv.hh"
#include "XrdOuc/XrdOucProg.hh"
#include "XrdOuc/XrdOucStream.hh"
#include "XrdOuc/XrdOucUtils.hh"
#include "XrdSys/XrdSysError.hh"
#include "XrdSys/XrdSysPthread.hh"
+ Include dependency graph for XrdOucProg.cc:

Go to the source code of this file.

Macros

#define runWithVec(strmP, theRC)
 

Macro Definition Documentation

◆ runWithVec

#define runWithVec (   strmP,
  theRC 
)
Value:
const char *argV[4]; int argC = 0;\
if (arg1) argV[argC++] = arg1;\
if (arg2) argV[argC++] = arg2;\
if (arg3) argV[argC++] = arg3;\
if (arg4) argV[argC++] = arg4;\
theRC = Run(strmP, argV, argC)

Definition at line 100 of file XrdOucProg.cc.

110{
111 char **myArgs;
112 int rc, totArgs = numArgs + argC;
113
114// If we have no program, return an error
115//
116 if (!ArgBuff)
117 {if (eDest) eDest->Emsg("Run", "No program specified");
118 return -ENOEXEC;
119 }
120
121// Copy arguments to stack storage (we could avoid this but not with the stack).
122//
123 myArgs = (char**)alloca(sizeof(char *) * (totArgs + 1));
124 if (numArgs) memcpy(myArgs, Arg, sizeof(char*)*numArgs);
125 if (argC) memcpy(&myArgs[numArgs], argV, sizeof(char*)*argC);
126 myArgs[totArgs] = 0;
127
128// If this is a local process then just execute it inline on this thread
129//
130 if (myProc) return (*myProc)(Sp, myArgs, totArgs);
131
132// Execute the command, possibly setting an environment.
133//
134 if (envV)
135 {XrdOucEnv progEnv, *oldEnv = Sp->SetEnv(&progEnv);
136 progEnv.PutPtr("XrdEnvars**", (void *)envV);
137 rc = Sp->Exec(myArgs, 1, theEFD);
138 Sp->SetEnv(oldEnv);
139 } else rc = Sp->Exec(myArgs, 1, theEFD);
140
141// Diagnose any errors
142//
143 if (rc)
144 {rc = Sp->LastError();
145 if (eDest) eDest->Emsg("Run", rc, "execute", Arg[0]);
146 return -rc;
147 }
148
149// All done, caller will drain output
150//
151 return 0;
152}
153
154/******************************************************************************/
155
156int XrdOucProg::Run(const char *argV[], int argC, const char *envV[]) const
157{
158 XrdOucStream cmd;
159 char *lp;
160 int rc;
161
162// Execute the command
163//
164 rc = Run(&cmd, argV, argC, envV);
165 if (rc) return rc;
166
167// Drain all output
168//
169 while((lp = cmd.GetLine()))
170 if (eDest && *lp) eDest->Emsg("Run", lp);
171
172// All done
173//
174 return RunDone(cmd);
175}
176
177/******************************************************************************/
178
179int XrdOucProg::Run(XrdOucStream *Sp, const char *arg1, const char *arg2,
180 const char *arg3, const char *arg4) const
181{
182 int rc;
183
184// Execute the command
185//
186 runWithVec(Sp, rc);
187 return rc;
188}
189
190/******************************************************************************/
191
192int XrdOucProg::Run(const char *arg1, const char *arg2,
193 const char *arg3, const char *arg4) const
194{
195 XrdOucStream cmd;
196 char *lp;
197 int rc;
198
199// Execute the command
200//
201 runWithVec(&cmd, rc);
202 if (rc) return rc;
203
204// Drain all output
205//
206 while((lp = cmd.GetLine()))
207 if (eDest && *lp) eDest->Emsg("Run", lp);
208
209// All done
210//
211 return RunDone(cmd);
212}
213
214/******************************************************************************/
215
216int XrdOucProg::Run(char *outBuff, int outBsz,
217 const char *arg1, const char *arg2,
218 const char *arg3, const char *arg4) const
219{
220 XrdOucStream cmd;
221 char *lp, *tp;
222 int n, rc;
223
224// Execute the command
225//
226 runWithVec(&cmd, rc);
227 if (rc) return rc;
228
229// Drain the first line to the output buffer
230//
231 if (outBuff && outBsz > 0)
232 {if ((lp = cmd.GetLine()))
233 {while (*lp && *lp == ' ') lp++;
234 if ((n = strlen(lp)))
235 {tp = lp+n-1;
236 while(*tp-- == ' ') n--;
237 if (n >= outBsz) n = outBsz-1;
238 strncpy(outBuff, lp, n); outBuff += n;
239 }
240 }
241 *outBuff = 0;
242 }
243
244// Drain remaining output
245//
246 while((lp = cmd.GetLine())) {}
247
248// All done
249//
250 return RunDone(cmd);
251}
252
253/******************************************************************************/
254/* R u n D o n e */
255/******************************************************************************/
256
257int XrdOucProg::RunDone(XrdOucStream &cmd) const
258{
259 int rc;
260
261// If this is an inline program then just return 0. There is no external process
262// and the return code was returned at the time the inline process was run.
263//
264 if (myProc) return 0;
265
266// Drain the command
267//
268 rc = cmd.Drain();
269
270// Determine ending status
271//
272 if (WIFSIGNALED(rc))
273 {if (eDest)
274 {char buff[16];
275 sprintf(buff, "%d", WTERMSIG(rc));
276 eDest->Emsg("Run", Arg[0], "killed by signal", buff);
277 }
278 return -EPIPE;
279 }
280 if (WIFEXITED(rc))
281 {rc = WEXITSTATUS(rc);
282 if (rc && eDest)
283 {char buff[16];
284 sprintf(buff, "%d", rc);
285 eDest->Emsg("Run", Arg[0], "ended with status", buff);
286 }
287 return -rc;
288 }
289 return 0; // We'll assume all went well here
290}
291
292/******************************************************************************/
293/* S e t u p */
294/******************************************************************************/
295
296int XrdOucProg::Setup(const char *prog, XrdSysError *errP,
297 int (*Proc)(XrdOucStream *, char **, int))
298{
299 static const int maxArgs = 65;
300 char *argV[maxArgs];
301 int rc;
302
303// Prepare to handle the program
304//
305 Reset();
306 if (!errP) errP = eDest;
307 myProc = 0;
308 ArgBuff = strdup(prog);
309
310// Construct the argv array based on passed command line.
311//
312 rc = XrdOucUtils::argList(ArgBuff, argV, maxArgs);
313 if (rc <= 0)
314 {if (errP)
315 {if (!rc || !argV[0])
316 {const char *pgm = (Proc ? "procedure" : "program");
317 errP->Emsg("Run", pgm, "name not specified.");
318 } else errP->Emsg("Run", rc, "set up", argV[0]);
319 }
320 return (rc ? rc : -EINVAL);
321 }
322
323// Record the arguments including the phamtom null pointer. We must have
324// atleast one, the program or procedure name.
325//
326 numArgs = rc;
327 Arg = new char*[rc+1];
328 memcpy(Arg, argV, sizeof(char *) * (rc+1));
329
330// If this is a local process then just record its address
331//
332 if ((myProc = Proc)) return 0;
333
334// Make sure the program is really executable
335//
336 if (access(Arg[0], X_OK))
337 {rc = errno;
338 if (errP) errP->Emsg("Run", rc, "set up", Arg[0]);
339 Reset();
340 return rc;
341 }
342 return 0;
343}
344
345/******************************************************************************/
346/* S t a r t */
347/******************************************************************************/
348
350{
351
352// Create a stream for this command (it is an eror if we are already started)
353//
354 if (myStream) return EBUSY;
355 if (!(myStream = new XrdOucStream(eDest))) return ENOMEM;
356
357// Execute the command and let it linger
358//
359 theEFD = 0;
360 return Run(myStream);
361}
362
363/******************************************************************************/
364/* P r i v a t e M e t h o d s */
365/******************************************************************************/
366/******************************************************************************/
367/* R e s e t */
368/******************************************************************************/
369
370void XrdOucProg::Reset()
371{
372
373 if (ArgBuff) {free(ArgBuff); ArgBuff = 0;}
374 if (numArgs) delete [] Arg;
375 Arg = &ArgBuff;
376 numArgs = 0;
377}
378
379/******************************************************************************/
380/* R e s t a r t */
381/******************************************************************************/
382
383int XrdOucProg::Restart()
384{
385 myStream->Close();
386 return Run(myStream);
387}
static XrdSysError eDest(0,"crypto_")
#define runWithVec(strmP, theRC)
#define access(a, b)
Definition XrdPosix.hh:44
void PutPtr(const char *varname, void *value)
Definition XrdOucEnv.cc:298
int Start(void)
int RunDone(XrdOucStream &cmd) const
int Run(XrdOucStream *Sp, const char *argV[], int argc=0, const char *envV[]=0) const
int Setup(const char *prog, XrdSysError *errP=0, int(*Proc)(XrdOucStream *, char **, int)=0)
char * GetLine()
void Close(int hold=0)
static int argList(char *args, char **argV, int argC)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)