00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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);
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
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
00147 BASE_LOG("before last scavenge");
00148 stooge.close_input();
00149 portable::sleep_ms(400);
00150 stooge_thread.stop();
00151
00152
00153
00154
00155
00156
00157
00158
00159 BASE_LOG("after last scavenge");
00160
00161 }
00162
00163 #undef static_class_name
00164