Back to index

texmacs  1.0.7.15
qt_pipe_link.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : qt_pipe_link.cpp
00004 * DESCRIPTION: TeXmacs links by pipes
00005 * COPYRIGHT  : (C) 2000  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "basic.hpp"
00013 
00014 #if defined (QTTEXMACS) && (defined (__MINGW__) || defined (__MINGW32__) || defined (QTPIPES))
00015 
00016 #include "tm_link.hpp"
00017 #include "QTMPipeLink.hpp"
00018 #include "hashset.hpp"
00019 #include "iterator.hpp"
00020 #include "timer.hpp"
00021 
00022 #include <sys/types.h>
00023 #include <signal.h>
00024 #if defined(__MINGW__) || defined(__MINGW32__)
00025 #else
00026 #  include <sys/wait.h>
00027 #endif
00028 
00029 hashset<pointer> pipe_link_set;
00030 
00031 /******************************************************************************
00032 * Definition of qt_pipe_link_rep class
00033 ******************************************************************************/
00034 
00035 struct qt_pipe_link_rep: tm_link_rep {
00036   QTMPipeLink PipeLink;
00037 
00038 public:
00039   qt_pipe_link_rep (string cmd);
00040   ~qt_pipe_link_rep ();
00041 
00042   string  start ();
00043   void    write (string s, int channel);
00044   string& watch (int channel);
00045   string  read (int channel);
00046   void    listen (int msecs);
00047   bool    is_readable (int channel);
00048   void    interrupt ();
00049   void    stop ();
00050   void    feed (int channel);
00051 };
00052 
00053 qt_pipe_link_rep::qt_pipe_link_rep (string cmd) : PipeLink (cmd) {
00054   PipeLink.feed_cmd = &feed_cmd;
00055   pipe_link_set->insert ((pointer) this);
00056   alive = false;
00057 }
00058 
00059 qt_pipe_link_rep::~qt_pipe_link_rep () {
00060   stop ();
00061   pipe_link_set->remove ((pointer) this);
00062 }
00063 
00064 /******************************************************************************
00065 * Routines for qt_pipe_links
00066 ******************************************************************************/
00067 
00068 string
00069 qt_pipe_link_rep::start () {
00070   if (alive) return "busy";
00071   if (DEBUG_AUTO) cerr << "TeXmacs] Launching '" << PipeLink.cmd << "'\n";
00072   if (! PipeLink.launchCmd ()) {
00073     if (DEBUG_AUTO) cerr << "TeXmacs] Error: cannot start '" << PipeLink.cmd << "'\n";
00074     return "Error: cannot start application";
00075   }
00076   alive= true;
00077   return "ok";
00078 }
00079 
00080 void
00081 qt_pipe_link_rep::write (string s, int channel) {
00082   if ((!alive) || (channel != LINK_IN)) return;
00083   if (-1 == PipeLink.writeStdin (s)) {
00084     cerr << "TeXmacs] Error: cannot write to '" << PipeLink.cmd << "'\n";
00085     PipeLink.killProcess ();
00086   }
00087 }
00088 
00089 void
00090 qt_pipe_link_rep::feed (int channel) {
00091   if ((!alive) || ((channel != LINK_OUT) && (channel != LINK_ERR))) return;
00092   if (channel == LINK_OUT) PipeLink.feedBuf (QProcess::StandardOutput);
00093   else PipeLink.feedBuf (QProcess::StandardError);
00094 }
00095 
00096 string&
00097 qt_pipe_link_rep::watch (int channel) {
00098   static string empty_string= "";
00099   if (channel == LINK_OUT) return PipeLink.getOutbuf ();
00100   else if (channel == LINK_ERR) return PipeLink.getErrbuf ();
00101   else  return empty_string;
00102 }
00103 
00104 string
00105 qt_pipe_link_rep::read (int channel) {
00106   if (channel == LINK_OUT) {
00107     string r= PipeLink.getOutbuf ();
00108     PipeLink.setOutbuf ("");
00109     return r;
00110   }
00111   else if (channel == LINK_ERR) {
00112     string r= PipeLink.getErrbuf ();
00113     PipeLink.setErrbuf ("");
00114     return r;
00115   }
00116   else return string("");
00117 }
00118 
00119 void
00120 qt_pipe_link_rep::listen (int msecs) {
00121   if (!alive) return;
00122   time_t wait_until= texmacs_time () + msecs;
00123   while ((PipeLink.getOutbuf() == "") && (PipeLink.getErrbuf() == "")) {
00124     PipeLink.listenChannel (QProcess::StandardOutput, 0);
00125     PipeLink.listenChannel (QProcess::StandardError, 0);
00126     if (texmacs_time () - wait_until > 0) break;
00127   }
00128 }
00129 
00130 bool
00131 qt_pipe_link_rep::is_readable (int channel) {
00132   if ((!alive) || ((channel != LINK_OUT) && (channel != LINK_ERR))) return false;
00133   if (channel == LINK_OUT) PipeLink.listenChannel (QProcess::StandardOutput, 0);
00134   else PipeLink.listenChannel (QProcess::StandardError, 0);
00135 }
00136 
00137 void
00138 qt_pipe_link_rep::interrupt () {
00139   if (!alive) return;
00140 #if defined(__MINGW__) || defined(__MINGW32__)
00141   // Not implemented
00142 #else
00143   ::killpg(PipeLink.pid (), SIGINT);
00144 #endif
00145 }
00146 
00147 void
00148 qt_pipe_link_rep::stop () {
00149   PipeLink.killProcess ();
00150   alive= false;
00151 }
00152 
00153 /******************************************************************************
00154 * Main builder function for qt_pipe_links
00155 ******************************************************************************/
00156 
00157 tm_link
00158 make_pipe_link (string cmd) {
00159   return tm_new<qt_pipe_link_rep> (cmd);
00160 }
00161 
00162 /******************************************************************************
00163 * Emergency exit for all pipes
00164 ******************************************************************************/
00165 
00166 void
00167 close_all_pipes () {
00168   iterator<pointer> it= iterate (pipe_link_set);
00169   while (it->busy()) {
00170     qt_pipe_link_rep* con= (qt_pipe_link_rep*) it->next();
00171     if (con->alive) con->stop ();
00172   }
00173 }
00174 
00175 void
00176 process_all_pipes () {
00177   iterator<pointer> it= iterate (pipe_link_set);
00178   while (it->busy()) {
00179     qt_pipe_link_rep* con= (qt_pipe_link_rep*) it->next();
00180     if (con->alive) con->apply_command ();
00181   }
00182 }
00183 
00184 #endif // defined (QTTEXMACS) && (defined (__MINGW__) || defined (__MINGW32__))