xorp

run_command.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 // vim:set sts=4 ts=8:
00003 
00004 // Copyright (c) 2001-2011 XORP, Inc and Others
00005 //
00006 // This program is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU Lesser General Public License, Version
00008 // 2.1, June 1999 as published by the Free Software Foundation.
00009 // Redistribution and/or modification of this program under the terms of
00010 // any other version of the GNU Lesser General Public License is not
00011 // permitted.
00012 // 
00013 // This program is distributed in the hope that it will be useful, but
00014 // WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00016 // see the GNU Lesser General Public License, Version 2.1, a copy of
00017 // which can be found in the XORP LICENSE.lgpl file.
00018 // 
00019 // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00020 // http://xorp.net
00021 
00022 
00023 #ifndef __LIBXORP_RUN_COMMAND_HH__
00024 #define __LIBXORP_RUN_COMMAND_HH__
00025 
00026 
00027 
00028 
00029 #include "libxorp/asyncio.hh"
00030 #include "libxorp/callback.hh"
00031 #include "libxorp/timer.hh"
00032 
00033 class EventLoop;
00034 
00035 
00039 class RunCommandBase {
00040 public:
00041     class ExecId;
00042 
00051     RunCommandBase(EventLoop&       eventloop,
00052            const string&    command,
00053            const string&    real_command_name,
00054            int          task_priority =
00055            XorpTask::PRIORITY_DEFAULT);
00056 
00060     virtual ~RunCommandBase();
00061 
00067     void set_argument_list(const list<string>& v) { _argument_list = v; }
00068 
00074     int execute();
00075 
00079     void terminate();
00080 
00084     void terminate_with_prejudice();
00085 
00091     const string& command() const { return _command; }
00092 
00098     const list<string>& argument_list() const { return _argument_list; }
00099 
00105     void wait_status_changed(int wait_status);
00106 
00112     bool is_exited() const { return _command_is_exited; }
00113 
00120     bool is_signal_terminated() const { return _command_is_signal_terminated; }
00121 
00127     bool is_coredumped() const { return _command_is_coredumped; }
00128 
00134     bool is_stopped() const { return _command_is_stopped; }
00135 
00141     int exit_status() const { return _command_exit_status; }
00142 
00148     int term_signal() const { return _command_term_signal; }
00149 
00155     int stop_signal() const { return _command_stop_signal; }
00156 
00162     int task_priority() const { return _task_priority; }
00163 
00170     ExecId& exec_id() { return (_exec_id); }
00171 
00177     void set_exec_id(const ExecId& v);
00178 
00182     class ExecId {
00183     public:
00187     ExecId();
00188 
00194     ExecId(uid_t uid);
00195 
00202     ExecId(uid_t uid, gid_t gid);
00203 
00207     void save_current_exec_id();
00208 
00215     int restore_saved_exec_id(string& error_msg) const;
00216 
00223     int set_effective_exec_id(string& error_msg);
00224 
00230     bool is_set() const;
00231 
00237     uid_t   uid() const { return (_uid); }
00238 
00244     gid_t   gid() const { return (_gid); }
00245 
00251     void    set_uid(uid_t v) { _uid = v; _is_uid_set = true; }
00252 
00258     void    set_gid(gid_t v) { _gid = v; _is_gid_set = true; }
00259 
00265     bool    is_uid_set() const { return (_is_uid_set); }
00266 
00272     bool    is_gid_set() const { return (_is_gid_set); }
00273 
00277     void    reset();
00278 
00279     private:
00280     uid_t   saved_uid() const { return (_saved_uid); }
00281     uid_t   saved_gid() const { return (_saved_gid); }
00282 
00283     uid_t   _uid;
00284     gid_t   _gid;
00285     bool    _is_uid_set;
00286     bool    _is_gid_set;
00287 
00288     uid_t   _saved_uid;
00289     gid_t   _saved_gid;
00290     bool    _is_exec_id_saved;
00291     };
00292 
00293 private:
00300     virtual void stdout_cb_dispatch(const string& output) = 0;
00301 
00308     virtual void stderr_cb_dispatch(const string& output) = 0;
00309 
00317     virtual void done_cb_dispatch(bool success, const string& error_msg) = 0;
00318 
00324     virtual void stopped_cb_dispatch(int stop_signal) = 0;
00325 
00332     virtual bool redirect_stderr_to_stdout() const = 0;
00333 
00337     void cleanup();
00338 
00342     int block_child_signals();
00343 
00347     int unblock_child_signals();
00348 
00355     void terminate_process(bool with_prejudice);
00356 
00360     void close_output();
00361 
00365     void close_stdout_output();
00366 
00370     void close_stderr_output();
00371 
00377     void set_command_status(int status);
00378 
00387     void append_data(AsyncFileOperator::Event event, const uint8_t* buffer,
00388              size_t buffer_bytes, size_t offset);
00389 
00399     void io_done(AsyncFileOperator::Event event, int error_code);
00400 
00406     void done(XorpTimer& done_timer);
00407 
00408 #ifdef HOST_OS_WINDOWS
00409     static const int WIN32_PROC_TIMEOUT_MS = 500;
00410 
00411     void win_proc_done_cb(XorpFd fd, IoEventType type);
00412     void win_proc_reaper_cb();
00413 #endif
00414 
00415     static const size_t BUF_SIZE = 8192;
00416     EventLoop&      _eventloop;
00417 
00418     string      _command;
00419     string      _real_command_name;
00420     list<string>    _argument_list;
00421 
00422     AsyncFileReader*    _stdout_file_reader;
00423     AsyncFileReader*    _stderr_file_reader;
00424     FILE*       _stdout_stream;
00425     FILE*       _stderr_stream;
00426     uint8_t     _stdout_buffer[BUF_SIZE];
00427     uint8_t     _stderr_buffer[BUF_SIZE];
00428     size_t      _last_stdout_offset;
00429     size_t      _last_stderr_offset;
00430     pid_t       _pid;
00431 #ifdef HOST_OS_WINDOWS
00432     HANDLE      _ph;
00433     XorpTimer       _reaper_timer;
00434 #endif
00435     bool        _is_error;
00436     string      _error_msg;
00437     bool        _is_running;
00438     ExecId      _exec_id;
00439 
00440     bool        _command_is_exited;
00441     bool        _command_is_signal_terminated;
00442     bool        _command_is_coredumped;
00443     bool        _command_is_stopped;
00444     int         _command_exit_status;
00445     int         _command_term_signal;
00446     int         _command_stop_signal;
00447     XorpTimer       _done_timer;
00448 
00449     bool        _stdout_eof_received;
00450     bool        _stderr_eof_received;
00451 
00452     int         _task_priority;
00453 };
00454 
00458 class RunCommand : public RunCommandBase {
00459 public:
00460     typedef XorpCallback2<void, RunCommand*, const string&>::RefPtr OutputCallback;
00461     typedef XorpCallback3<void, RunCommand*, bool, const string&>::RefPtr DoneCallback;
00462     typedef XorpCallback2<void, RunCommand*, int>::RefPtr StoppedCallback;
00463 
00479     RunCommand(EventLoop&           eventloop,
00480            const string&            command,
00481            const list<string>&      argument_list,
00482            RunCommand::OutputCallback   stdout_cb,
00483            RunCommand::OutputCallback   stderr_cb,
00484            RunCommand::DoneCallback     done_cb,
00485            bool             redirect_stderr_to_stdout,
00486            int task_priority = XorpTask::PRIORITY_DEFAULT);
00487 
00493     void set_stopped_cb(StoppedCallback cb) { _stopped_cb = cb; }
00494 
00495 private:
00501     void stdout_cb_dispatch(const string& output) {
00502     _stdout_cb->dispatch(this, output);
00503     }
00504 
00510     void stderr_cb_dispatch(const string& output) {
00511     _stderr_cb->dispatch(this, output);
00512     }
00513 
00521     void done_cb_dispatch(bool success, const string& error_msg) {
00522     _done_cb->dispatch(this, success, error_msg);
00523     }
00524 
00530     void stopped_cb_dispatch(int stop_signal) {
00531     if (! _stopped_cb.is_empty())
00532         _stopped_cb->dispatch(this, stop_signal);
00533     }
00534 
00541     bool redirect_stderr_to_stdout() const {
00542     return (_redirect_stderr_to_stdout);
00543     }
00544 
00545     OutputCallback  _stdout_cb;
00546     OutputCallback  _stderr_cb;
00547     DoneCallback    _done_cb;
00548     StoppedCallback _stopped_cb;
00549 
00550     bool        _redirect_stderr_to_stdout;
00551 };
00552 
00556 class RunShellCommand : public RunCommandBase {
00557 public:
00558     typedef XorpCallback2<void, RunShellCommand*, const string&>::RefPtr OutputCallback;
00559     typedef XorpCallback3<void, RunShellCommand*, bool, const string&>::RefPtr DoneCallback;
00560     typedef XorpCallback2<void, RunShellCommand*, int>::RefPtr StoppedCallback;
00561 
00576     RunShellCommand(EventLoop&              eventloop,
00577             const string&           command,
00578             const string&           argument_string,
00579             RunShellCommand::OutputCallback stdout_cb,
00580             RunShellCommand::OutputCallback stderr_cb,
00581             RunShellCommand::DoneCallback   done_cb,
00582             int task_priority = XorpTask::PRIORITY_DEFAULT);
00583 
00589     void set_stopped_cb(StoppedCallback cb) { _stopped_cb = cb; }
00590 
00591 private:
00597     void stdout_cb_dispatch(const string& output) {
00598     _stdout_cb->dispatch(this, output);
00599     }
00600 
00606     void stderr_cb_dispatch(const string& output) {
00607     _stderr_cb->dispatch(this, output);
00608     }
00609 
00617     void done_cb_dispatch(bool success, const string& error_msg) {
00618     _done_cb->dispatch(this, success, error_msg);
00619     }
00620 
00626     void stopped_cb_dispatch(int stop_signal) {
00627     if (! _stopped_cb.is_empty())
00628         _stopped_cb->dispatch(this, stop_signal);
00629     }
00630 
00637     bool redirect_stderr_to_stdout() const {
00638     //
00639     // XXX: Redirecting stderr to stdout is always disabled by defailt.
00640     // If we want stderr to be redirected, this should be specified
00641     // by the executed command itself. E.g.:
00642     //     "my_command my_args 2>&1"
00643     //
00644     return (false);
00645     }
00646 
00647     OutputCallback  _stdout_cb;
00648     OutputCallback  _stderr_cb;
00649     DoneCallback    _done_cb;
00650     StoppedCallback _stopped_cb;
00651 };
00652 
00653 #endif // __LIBXORP_RUN_COMMAND_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations