Ignore:
Timestamp:
02/18/08 23:21:23 (5 years ago)
Author:
Michael Medin <michael@…>
Branches:
master, 0.4.0, 0.4.1, 0.4.2, stable
Children:
95e4ace
Parents:
c1fe385
Message:

+ Added propper output handling to process subsystem (now you can execute programs tat return "much" data.

+ Added select support for SSL_write (now you can send "any amount of data" to the (SSL) socket.

Since check_nrpe doesn't do this it wont work in that end, but still...

File:
1 edited

Legend:

Unmodified
Added
Removed
  • modules/NRPEListener/NRPEListener.cpp

    r7a156f4 r394f7a1  
    2424#include <time.h> 
    2525#include <config.h> 
    26 #include "NRPEPacket.h" 
    2726#include <msvc_wrappers.h> 
    2827 
     
    128127    return false; 
    129128  } 
     129  root_ = NSCModuleHelper::getBasePath(); 
    130130 
    131131  return true; 
     
    228228    return NSCModuleHelper::InjectSplitAndCommand(t.first, sTarget, '!', message, perf); 
    229229  } else if (cd.type == script) { 
    230     return executeNRPECommand(args, message, perf); 
     230    int result = process::executeProcess(root_, args, message, perf, timeout); 
     231    if (!NSCHelper::isNagiosReturnCode(result)) { 
     232      NSC_LOG_ERROR_STD(_T("The command (") + command.c_str() + _T(") returned an invalid return code: ") + strEx::itos(result)); 
     233      return NSCAPI::returnUNKNOWN; 
     234    } 
     235    return NSCHelper::int2nagios(result); 
    231236  } else if (cd.type == script_dir) { 
    232237    std::wstring args = arrayBuffer::arrayBuffer2string(char_args, argLen, _T(" ")); 
    233238    std::wstring cmd = scriptDirectory_ + command.c_str() + _T(" ") +args; 
    234     return executeNRPECommand(cmd, message, perf); 
     239    int result = process::executeProcess(root_, cmd, message, perf, timeout); 
     240    if (!NSCHelper::isNagiosReturnCode(result)) { 
     241      NSC_LOG_ERROR_STD(_T("The command (") + command.c_str() + _T(") returned an invalid return code: ") + strEx::itos(result)); 
     242      return NSCAPI::returnUNKNOWN; 
     243    } 
     244    return NSCHelper::int2nagios(result); 
    235245  } else { 
    236246    NSC_LOG_ERROR_STD(_T("Unknown script type: ") + command.c_str()); 
     
    239249 
    240250} 
    241 int NRPEListener::executeNRPECommand(std::wstring command, std::wstring &msg, std::wstring &perf) 
    242 { 
    243   NSCAPI::nagiosReturn result; 
    244   PROCESS_INFORMATION pi; 
    245   STARTUPINFO si; 
    246   HANDLE hChildOutR, hChildOutW, hChildInR, hChildInW; 
    247   SECURITY_ATTRIBUTES sec; 
    248   DWORD dwstate, dwexitcode; 
    249   int retval; 
    250  
    251  
    252   // Set up members of SECURITY_ATTRIBUTES structure.  
    253  
    254   sec.nLength = sizeof(SECURITY_ATTRIBUTES); 
    255   sec.bInheritHandle = TRUE; 
    256   sec.lpSecurityDescriptor = NULL; 
    257  
    258   // Create Pipes 
    259   CreatePipe(&hChildInR, &hChildInW, &sec, 0); 
    260   CreatePipe(&hChildOutR, &hChildOutW, &sec, 0); 
    261  
    262   // Set up members of STARTUPINFO structure.  
    263  
    264   ZeroMemory(&si, sizeof(STARTUPINFO)); 
    265   si.cb = sizeof(STARTUPINFO); 
    266   si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; 
    267   si.hStdInput = hChildInR; 
    268   si.hStdOutput = hChildOutW; 
    269   si.hStdError = hChildOutW; 
    270   si.wShowWindow = SW_HIDE; 
    271  
    272  
    273   // CreateProcess doesn't work with a const command 
    274   TCHAR *cmd = new TCHAR[command.length()+1]; 
    275   wcsncpy_s(cmd, command.length()+1, command.c_str(), command.length()); 
    276   cmd[command.length()] = 0; 
    277   std::wstring root = NSCModuleHelper::getBasePath(); 
    278  
    279   // Create the child process.  
    280   BOOL processOK = CreateProcess(NULL, cmd,        // command line  
    281     NULL, // process security attributes  
    282     NULL, // primary thread security attributes  
    283     TRUE, // handles are inherited  
    284     0,    // creation flags  
    285     NULL, // use parent's environment  
    286     root.c_str(), // use parent's current directory  
    287     &si,  // STARTUPINFO pointer  
    288     &pi); // receives PROCESS_INFORMATION  
    289   delete [] cmd; 
    290  
    291   if (processOK) { 
    292     dwstate = WaitForSingleObject(pi.hProcess, 1000*timeout); 
    293     CloseHandle(hChildInR); 
    294     CloseHandle(hChildInW); 
    295     CloseHandle(hChildOutW); 
    296  
    297     if (dwstate == WAIT_TIMEOUT) { 
    298       TerminateProcess(pi.hProcess, 5); 
    299       msg = _T("The check (") + command + _T(") didn't respond within the timeout period (") + strEx::itos(timeout) + _T("s)!"); 
    300       result = NSCAPI::returnUNKNOWN; 
    301     } else { 
    302       DWORD dwread; 
    303       std::string str; 
    304 #define BUFF_SIZE 4096 
    305       char *buf = new char[BUFF_SIZE+1]; 
    306       do { 
    307         retval = ReadFile(hChildOutR, buf, BUFF_SIZE, &dwread, NULL); 
    308         if (retval == 0) 
    309           break; 
    310         if (dwread > BUFF_SIZE) 
    311           break; 
    312         buf[dwread] = 0; 
    313         str += buf; 
    314       } while (dwread == BUFF_SIZE); 
    315       delete [] buf; 
    316       if (str.empty()) { 
    317         msg = _T("No output available from command..."); 
    318       } else { 
    319         msg = strEx::string_to_wstring(str); 
    320         strEx::token t = strEx::getToken(msg, '|'); 
    321         msg = t.first; 
    322         std::wstring::size_type pos = msg.find_last_not_of(_T("\n\r ")); 
    323         if (pos != std::wstring::npos) { 
    324           if (pos == msg.size()) 
    325             msg = msg.substr(0,pos); 
    326           else 
    327             msg = msg.substr(0,pos+1); 
    328         } 
    329         perf = t.second; 
    330       } 
    331       if (GetExitCodeProcess(pi.hProcess, &dwexitcode) == 0) { 
    332         NSC_LOG_ERROR(_T("Failed to get commands (") + command + _T(") return code: ") + error::lookup::last_error()); 
    333         dwexitcode = NSCAPI::returnUNKNOWN; 
    334       } 
    335       if (!NSCHelper::isNagiosReturnCode(dwexitcode)) { 
    336         NSC_LOG_ERROR(_T("The command (") + command + _T(") returned an invalid return code: ") + strEx::itos(dwexitcode)); 
    337         dwexitcode = NSCAPI::returnUNKNOWN; 
    338       } 
    339       result = NSCHelper::int2nagios(dwexitcode); 
    340     } 
    341     CloseHandle(pi.hThread); 
    342     CloseHandle(pi.hProcess); 
    343     CloseHandle(hChildOutR); 
    344   } 
    345   else { 
    346     msg = _T("NRPE_NT failed to create process (") + command + _T("): ") + error::lookup::last_error(); 
    347     result = NSCAPI::returnUNKNOWN; 
    348     CloseHandle(hChildInR); 
    349     CloseHandle(hChildInW); 
    350     CloseHandle(hChildOutW); 
    351     CloseHandle(pi.hThread); 
    352     CloseHandle(pi.hProcess); 
    353     CloseHandle(hChildOutR); 
    354   } 
    355   return result; 
    356 } 
     251 
    357252void NRPEListener::onClose() 
    358253{} 
     
    400295        return; 
    401296      } 
    402       client->send(block); 
     297      int maxWait = socketTimeout_*10; 
     298      for (i=0;i<maxWait;i++) { 
     299        bool lastReadHasMore = false; 
     300        try { 
     301          if (client->canWrite()) 
     302            lastReadHasMore = client->sendAll(block); 
     303        } catch (simpleSocket::SocketException e) { 
     304          NSC_LOG_MESSAGE(_T("Could not send NRPE packet from socket :") + e.getMessage()); 
     305          client->close(); 
     306          return; 
     307        } 
     308        if (!lastReadHasMore) { 
     309          client->close(); 
     310          return; 
     311        } 
     312        Sleep(100); 
     313      } 
     314      if (i >= maxWait) { 
     315        NSC_LOG_ERROR_STD(_T("Timeout reading NRPE-packet (increase socket_timeout)")); 
     316        client->close(); 
     317        return; 
     318      } 
    403319    } 
    404320  } catch (simpleSocket::SocketException e) { 
     
    406322  } catch (NRPEException e) { 
    407323    NSC_LOG_ERROR_STD(_T("NRPEException: ") + e.getMessage()); 
     324  } catch (...) { 
     325    NSC_LOG_ERROR_STD(_T("Unhandled Exception in NRPE listner...")); 
    408326  } 
    409327  client->close(); 
     
    413331  if (p.getType() != NRPEPacket::queryPacket) { 
    414332    NSC_LOG_ERROR(_T("Request is not a query.")); 
    415     throw NRPEException(_T("Invalid query type")); 
     333    throw NRPEException(_T("Invalid query type: ") + strEx::itos(p.getType())); 
    416334  } 
    417335  if (p.getVersion() != NRPEPacket::version2) { 
     
    470388      ret = NSCAPI::returnUNKNOWN; 
    471389  } 
    472   if (msg.length() > buffer_length_) { 
     390  if (msg.length() >= buffer_length_) { 
    473391    NSC_LOG_ERROR(_T("Truncating returndata as it is bigger then NRPE allowes :(")); 
    474392    msg = msg.substr(0,buffer_length_-1); 
Note: See TracChangeset for help on using the changeset viewer.