1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/ExternalProgram.h
13 #ifndef ZYPP_EXTERNALPROGRAM_H
14 #define ZYPP_EXTERNALPROGRAM_H
22 #include "zypp/base/ExternalDataSource.h"
23 #include "zypp/Pathname.h"
28 * @short Execute a program and give access to its io
29 * An object of this class encapsulates the execution of
30 * an external program. It starts the program using fork
31 * and some exec.. call, gives you access to the program's
32 * stdio and closes the program after use.
36 * const char* argv[] =
44 * ExternalProgram prog( argv,
45 * ExternalProgram::Discard_Stderr,
48 * for(line = prog.receiveLine();
50 * line = prog.receiveLine() )
58 class ExternalProgram : public zypp::externalprogram::ExternalDataSource
63 typedef std::vector<std::string> Arguments;
66 * Define symbols for different policies on the handling
69 enum Stderr_Disposition {
78 * For passing additional environment variables to set
80 typedef std::map<std::string,std::string> Environment;
83 * Start the external program by using the shell <tt>/bin/sh<tt>
84 * with the option <tt>-c</tt>. You can use io direction symbols < and >.
85 * @param commandline a shell commandline that is appended to
86 * <tt>/bin/sh -c</tt>.
87 * @param default_locale whether to set LC_ALL=C before starting
88 * @param root directory to chroot into, / or empty to not chroot
90 ExternalProgram (std::string commandline,
91 Stderr_Disposition stderr_disp = Normal_Stderr,
92 bool use_pty = false, int stderr_fd = -1, bool default_locale = false,
93 const Pathname& root = "");
96 * Start an external program by giving the arguments as an arry of char *pointers.
97 * If environment is provided, varaiables will be added to the childs environment,
98 * overwriting existing ones.
100 * Stdin redirection: If the \b 1st argument starts with a \b '<', the remaining
101 * part is treated as file opened for reading on standard input (or \c /dev/null
105 * const char* argv[] = { "</tmp/x", "cat", NULL };
106 * ExternalProgram prog( argv );
112 ExternalProgram (const Arguments &argv,
113 Stderr_Disposition stderr_disp = Normal_Stderr,
114 bool use_pty = false, int stderr_fd = -1, bool default_locale = false,
115 const Pathname& root = "");
117 ExternalProgram (const Arguments &argv, const Environment & environment,
118 Stderr_Disposition stderr_disp = Normal_Stderr,
119 bool use_pty = false, int stderr_fd = -1, bool default_locale = false,
120 const Pathname& root = "");
122 ExternalProgram (const char *const *argv,
123 Stderr_Disposition stderr_disp = Normal_Stderr,
124 bool use_pty = false, int stderr_fd = -1, bool default_locale = false,
125 const Pathname& root = "");
127 ExternalProgram (const char *const *argv, const Environment & environment,
128 Stderr_Disposition stderr_disp = Normal_Stderr,
129 bool use_pty = false, int stderr_fd = -1, bool default_locale = false,
130 const Pathname& root = "");
132 ExternalProgram (const char *binpath, const char *const *argv_1,
133 bool use_pty = false);
136 ExternalProgram (const char *binpath, const char *const *argv_1, const Environment & environment,
137 bool use_pty = false);
142 /** Wait for the progamm to complete. */
151 * Return whether program is running
158 pid_t getpid() { return pid; }
160 /** The command we're executing. */
161 const std::string & command() const
164 /** Some detail telling why the execution failed, if it failed.
165 * Empty if the command is still running or successfully completed.
167 * \li <tt>Can't open pty (%s).</tt>
168 * \li <tt>Can't open pipe (%s).</tt>
169 * \li <tt>Can't fork (%s).</tt>
170 * \li <tt>Command exited with status %d.</tt>
171 * \li <tt>Command was killed by signal %d (%s).</tt>
173 const std::string & execError() const
174 { return _execError; }
177 * origfd will be accessible as newfd and closed (unless they were equal)
179 static void renumber_fd (int origfd, int newfd);
184 * Redirect all command output to an \c ostream.
185 * Returns when the command has completed.
187 * std::ostringstream s;
188 * ExternalProgram("pwd") >> s;
189 * SEC << s.str() << endl;
192 * std::ostringstream s;
193 * ExternalProgram prog("ls -l wrzl");
195 * if ( prog.close() == 0 )
196 * MIL << s.str() << endl;
198 * ERR << prog.execError() << endl;
201 std::ostream & operator>>( std::ostream & out_r );
204 int checkStatus( int );
209 * Set to true, if a pair of ttys is used for communication
210 * instead of a pair of pipes.
216 /** Store the command we're executing. */
217 std::string _command;
218 /** Remember execution errors like failed fork/exec. */
219 std::string _execError;
221 void start_program (const char *const *argv, const Environment & environment,
222 Stderr_Disposition stderr_disp = Normal_Stderr,
223 int stderr_fd = -1, bool default_locale = false,
224 const char* root = NULL);
229 namespace _ExternalProgram
231 /** Helper providing pipe FDs for \ref ExternalProgramWithStderr.
232 * Moved to a basse class because the pipe needs to be initialized
233 * before the \ref ExternalProgram base class is initialized.
234 * \see \ref ExternalProgramWithStderr
241 void closeW() { if ( _fds[W] != -1 ) { ::close( _fds[W] ); _fds[W] = -1; } }
242 FILE * stderr() { return _stderr; }
249 /** ExternalProgram extended to offer reading programs stderr.
250 * \see \ref ExternalProgram
252 class ExternalProgramWithStderr : private _ExternalProgram::EarlyPipe, public ExternalProgram
255 ExternalProgramWithStderr( const Arguments & argv_r )
256 : ExternalProgram( argv_r, Stderr_To_FileDesc, /*use_pty*/false, _fds[W] )
259 ExternalProgramWithStderr( const Arguments & argv_r, const Environment & environment_r )
260 : ExternalProgram( argv_r, environment_r, Stderr_To_FileDesc, /*use_pty*/false, _fds[W] )
264 /** Return \c FILE* to read programms stderr (O_NONBLOCK set). */
265 using _ExternalProgram::EarlyPipe::stderr;
267 /** Read data up to \c delim_r from stderr (nonblocking).
268 * \note If \c delim_r is '\0', we read as much data as possible.
269 * \return \c false if data are not yet available (\c retval_r remains untouched then).
271 bool stderrGetUpTo( std::string & retval_r, const char delim_r, bool returnDelim_r = false );
273 /** Read next complete line from stderr (nonblocking).
274 * \return \c false if data are not yet available (\c retval_r remains untouched then).
276 bool stderrGetline( std::string & retval_r, bool returnDelim_r = false )
277 { return stderrGetUpTo( retval_r, '\n', returnDelim_r ); }
280 /** Close write end of the pipe (childs end). */
290 #endif // ZYPP_EXTERNALPROGRAM_H