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 just 'cd' if '/'l; nothing if empty
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 * Initial args starting with \c # are discarded but some are treated specially:
101 * #/[path] - chdir to /[path] before executing
103 * Stdin redirection: If the \b 1st argument starts with a \b '<', the remaining
104 * part is treated as file opened for reading on standard input (or \c /dev/null
108 * const char* argv[] = { "</tmp/x", "cat", NULL };
109 * ExternalProgram prog( argv );
112 * Stdout redirection: If the \b 1st argument starts with a \b '>', the remaining
113 * part is treated as file opened for writing on standard output (or \c /dev/null
119 ExternalProgram (const Arguments &argv,
120 Stderr_Disposition stderr_disp = Normal_Stderr,
121 bool use_pty = false, int stderr_fd = -1, bool default_locale = false,
122 const Pathname& root = "");
124 ExternalProgram (const Arguments &argv, const Environment & environment,
125 Stderr_Disposition stderr_disp = Normal_Stderr,
126 bool use_pty = false, int stderr_fd = -1, bool default_locale = false,
127 const Pathname& root = "");
129 ExternalProgram (const char *const *argv,
130 Stderr_Disposition stderr_disp = Normal_Stderr,
131 bool use_pty = false, int stderr_fd = -1, bool default_locale = false,
132 const Pathname& root = "");
134 ExternalProgram (const char *const *argv, const Environment & environment,
135 Stderr_Disposition stderr_disp = Normal_Stderr,
136 bool use_pty = false, int stderr_fd = -1, bool default_locale = false,
137 const Pathname& root = "");
139 ExternalProgram (const char *binpath, const char *const *argv_1,
140 bool use_pty = false);
143 ExternalProgram (const char *binpath, const char *const *argv_1, const Environment & environment,
144 bool use_pty = false);
149 /** Wait for the progamm to complete. */
158 * Return whether program is running
165 pid_t getpid() { return pid; }
167 /** The command we're executing. */
168 const std::string & command() const
171 /** Some detail telling why the execution failed, if it failed.
172 * Empty if the command is still running or successfully completed.
174 * \li <tt>Can't open pty (%s).</tt>
175 * \li <tt>Can't open pipe (%s).</tt>
176 * \li <tt>Can't fork (%s).</tt>
177 * \li <tt>Command exited with status %d.</tt>
178 * \li <tt>Command was killed by signal %d (%s).</tt>
180 const std::string & execError() const
181 { return _execError; }
184 * origfd will be accessible as newfd and closed (unless they were equal)
186 static void renumber_fd (int origfd, int newfd);
191 * Redirect all command output to an \c ostream.
192 * Returns when the command has completed.
194 * std::ostringstream s;
195 * ExternalProgram("pwd") >> s;
196 * SEC << s.str() << endl;
199 * std::ostringstream s;
200 * ExternalProgram prog("ls -l wrzl");
202 * if ( prog.close() == 0 )
203 * MIL << s.str() << endl;
205 * ERR << prog.execError() << endl;
208 std::ostream & operator>>( std::ostream & out_r );
211 int checkStatus( int );
216 * Set to true, if a pair of ttys is used for communication
217 * instead of a pair of pipes.
223 /** Store the command we're executing. */
224 std::string _command;
225 /** Remember execution errors like failed fork/exec. */
226 std::string _execError;
228 void start_program (const char *const *argv, const Environment & environment,
229 Stderr_Disposition stderr_disp = Normal_Stderr,
230 int stderr_fd = -1, bool default_locale = false,
231 const char* root = NULL);
236 namespace externalprogram
238 /** Helper providing pipe FDs for \ref ExternalProgramWithStderr.
239 * Moved to a basse class because the pipe needs to be initialized
240 * before the \ref ExternalProgram base class is initialized.
241 * \see \ref ExternalProgramWithStderr
248 void closeW() { if ( _fds[W] != -1 ) { ::close( _fds[W] ); _fds[W] = -1; } }
249 FILE * stderr() { return _stderr; }
254 } // namespace externalprogram
256 /** ExternalProgram extended to offer reading programs stderr.
257 * \see \ref ExternalProgram
259 class ExternalProgramWithStderr : private externalprogram::EarlyPipe, public ExternalProgram
262 ExternalProgramWithStderr( const Arguments & argv_r )
263 : ExternalProgram( argv_r, Stderr_To_FileDesc, /*use_pty*/false, _fds[W] )
266 ExternalProgramWithStderr( const Arguments & argv_r, const Environment & environment_r )
267 : ExternalProgram( argv_r, environment_r, Stderr_To_FileDesc, /*use_pty*/false, _fds[W] )
271 /** Return \c FILE* to read programms stderr (O_NONBLOCK set). */
272 using externalprogram::EarlyPipe::stderr;
274 /** Read data up to \c delim_r from stderr (nonblocking).
275 * \note If \c delim_r is '\0', we read as much data as possible.
276 * \return \c false if data are not yet available (\c retval_r remains untouched then).
278 bool stderrGetUpTo( std::string & retval_r, const char delim_r, bool returnDelim_r = false );
280 /** Read next complete line from stderr (nonblocking).
281 * \return \c false if data are not yet available (\c retval_r remains untouched then).
283 bool stderrGetline( std::string & retval_r, bool returnDelim_r = false )
284 { return stderrGetUpTo( retval_r, '\n', returnDelim_r ); }
287 /** Close write end of the pipe (childs end). */
297 #endif // ZYPP_EXTERNALPROGRAM_H