t_redirection.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : test_stdio_redirecter                                             *
00004 *  Author : Chris Koeritz                                                     *
00005 *                                                                             *
00006 *  Purpose:                                                                   *
00007 *                                                                             *
00008 *    Tests out the stdio redirection class.                                   *
00009 *                                                                             *
00010 *******************************************************************************
00011 * Copyright (c) 2005-$now By Author.  This program is free software; you can  *
00012 * redistribute it and/or modify it under the terms of the GNU General Public  *
00013 * License as published by the Free Software Foundation; either version 2 of   *
00014 * the License or (at your option) any later version.  This is online at:      *
00015 *     http://www.fsf.org/copyleft/gpl.html                                    *
00016 * Please send any updates to: fred@gruntose.com                               *
00017 \*****************************************************************************/
00018 
00019 #include <basis/byte_array.h>
00020 #include <basis/function.h>
00021 #include <basis/istring.h>
00022 #include <basis/log_base.h>
00023 #include <basis/object_base.h>
00024 #include <mechanisms/ithread.h>
00025 #include <opsystem/command_line.h>
00026 #include <opsystem/redirecter.h>
00027 #include <data_struct/static_memory_gremlin.h>
00028 #include <textual/byte_format.h>
00029 
00030 #include <stdio.h>
00031 
00032 const int READ_INTERVAL = 30;
00033   // how frequently our thread looks for data.
00034 
00035 #undef LOG
00036 #define LOG(to_print) CLASS_EMERGENCY_LOG(program_wide_logger(), to_print)
00037 #undef BASE_LOG
00038 #define BASE_LOG(to_print) program_wide_logger().log(to_print)
00039 
00040 HOOPLE_STARTUP_CODE;
00041 
00043 
00044 class text_grabber : public ithread
00045 {
00046 public:
00047   text_grabber(stdio_redirecter &examine)
00048     : ithread(READ_INTERVAL), _stdio(examine) {}
00049 
00050   virtual ~text_grabber() {}
00051 
00052   IMPLEMENT_CLASS_NAME("text_grabber");
00053 
00054   void perform_activity(void *) {
00055     FUNCDEF("perform_activity");
00056     byte_array out;
00057     outcome ret = _stdio.read(out);
00058     out += '\0';
00059     if (ret == stdio_redirecter::OKAY) {
00060       BASE_LOG(istring("out> ") + (char *)out.observe());
00061     } else if ( (ret != stdio_redirecter::OKAY)
00062         && (ret != stdio_redirecter::NONE_READY) ) {
00063       LOG(istring("received error on read: ") + common::outcome_name(ret));
00064     }
00065 
00066     ret = _stdio.read_stderr(out);
00067     out += '\0';
00068     if (ret == stdio_redirecter::OKAY) {
00069       BASE_LOG(istring("err> ") + (char *)out.observe());
00070     } else if ( (ret != stdio_redirecter::OKAY)
00071         && (ret != stdio_redirecter::NONE_READY) ) {
00072       LOG(istring("received error on read_stderr: ")
00073           + common::outcome_name(ret));
00074     }
00075   }
00076 
00077 private:
00078   stdio_redirecter &_stdio;
00079 };
00080 
00082 
00083 #undef static_class_name
00084 #define static_class_name() "test_stdio_redirecter"
00085 
00086 int print_instructions()
00087 {
00088   BASE_LOG("\
00089 This program takes two arguments and runs a subprogram with redirected I/O.\n\
00090   --command cmdname\n\
00091       provides the program name to run.\n\
00092   --parms parmlist\n\
00093       provides the set of command line parameters to pass.\n\
00094 The parmslist should be enclosed in quotes in order to contain spaces.\n\
00095 Any embedded quotes should themselves be quoted as appropriate for the OS.\n");
00096 
00097   return 123;
00098 }
00099 
00100 int main(int argc, char *argv[])
00101 {
00102   FUNCDEF("main");
00103   command_line cmds(argc, argv);
00104   istring cmd;
00105   istring parms;
00106   if (!cmds.get_value("command", cmd)) return print_instructions();
00107 BASE_LOG(istring("got command: ") + cmd);
00108   if (!cmds.get_value("parms", parms)) return print_instructions();
00109 BASE_LOG(istring("got parms: ") + parms);
00110 
00111   stdio_redirecter stooge(cmd, parms);
00112   if (stooge.health() != stdio_redirecter::OKAY) {
00113     LOG(istring("failed to create the redirecter process: ")
00114        + common::outcome_name(stooge.health()));
00115     return 140;
00116   }
00117 
00118   text_grabber stooge_thread(stooge);  // reads the out and err from app.
00119   stooge_thread.start(NIL);
00120 
00121   bool first_input = true;
00122 
00123   bool done = false;
00124   while (!done) {
00125     BASE_LOG("Enter text to send to process (QUIT to exit):");
00126     istring in('\0', 257);
00127     fgets(in.access(), 256, stdin);
00128     in.shrink();
00129     if ( (in.length() >= 4) && (in.substring(0, 3) == "QUIT") ) break;
00130     if (in.length()) {
00131       int count;
00132       if (first_input) {
00133         // password likes a CRLF attached.
00134         in.zap(in.end(), in.end());
00135         in += "\r\n";
00137       }
00138       outcome ret = stooge.write(byte_array(in.length(), (byte *)in.s()), count);
00139       if (ret != stdio_redirecter::OKAY) {
00140         LOG(istring("received error on write: ") + common::outcome_name(ret));
00141       }
00142     }
00143     
00144   }
00145 
00146   // get last outputs from the program before it goes away.
00147 BASE_LOG("before last scavenge");
00148   stooge.close_input();  // make sure it knows we're done talking.
00149   portable::sleep_ms(400);
00150   stooge_thread.stop();
00151 /*
00152   outcome ret = stooge.read(out);
00153   if (ret == stdio_redirecter::OKAY) {
00154     BASE_LOG(istring("out> ") + (char *)out.observe());
00155   } else if ( (ret != stdio_redirecter::OKAY) && (ret != stdio_redirecter::NONE_READY) ) {
00156     LOG(istring("received error on read: ") + common::outcome_name(ret));
00157   }
00158 */
00159 BASE_LOG("after last scavenge");
00160 
00161 }
00162 
00163 #undef static_class_name
00164 

Generated on Fri Nov 21 04:30:14 2008 for HOOPLE Libraries by  doxygen 1.5.1