#ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef STDC_HEADERS #include #include #endif #ifdef HAVE_INTTYPES_H #include #else #ifdef HAVE_STDINT_H #include #endif #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #ifndef WIN32 #include #include #include #include #include #include #include #endif #ifdef WIN32 #if _MSC_VER > 1020 #pragma warning(disable: 4786) #endif #endif #include #include #include #ifdef WIN32 #include #define socklen_t int #define in_addr_t int #endif #ifndef INADDR_NONE #define INADDR_NONE 0xFFFFFFFF #endif using namespace std; class Processor { public: Processor() { bInit = false; }; virtual ~Processor() {}; virtual bool process(const char *in_str, string &out_str) = 0; bool bInit; }; class SocketProcessor : public Processor { public: SocketProcessor(int s); ~SocketProcessor(); virtual bool process(const char *in_str, string &out_str); protected: int m_s; }; SocketProcessor::SocketProcessor(int s) { m_s = s; if (s == -1) return; bool bCR = false; for (;;){ char c; int rs = recv(m_s, &c, 1, 0); if (rs <= 0) return; if (bCR && (c == '>')) break; bCR = (c == '\n'); } bInit = true; } SocketProcessor::~SocketProcessor() { if (m_s != -1) #ifdef WIN32 closesocket(m_s); #else close(m_s); #endif } bool SocketProcessor::process(const char *in_str, string &out_str) { if (m_s == -1) return false; string ss; ss = in_str; ss += "\n"; unsigned size = ss.length(); const char *p = ss.c_str(); while (size){ int ws = send(m_s, p, size, 0); if (ws <= 0) return false; size -= ws; } string out; bool bCR = false; for (;;){ char c; int rs = recv(m_s, &c, 1, 0); if (rs <= 0) return false; if (c == '\r') continue; if (bCR && (c == '>')) break; out += c; bCR = (c == '\n'); } out = out.substr(0, out.length() - 1); if ((out.length() >= 2) && (out.substr(0, 2) == "? ")){ out_str = "?"; out_str += out.substr(2); }else{ out_str += ">"; out_str += out; } return true; } #ifdef WIN32 #define WS_VERSION_REQD 0x0101 #endif Processor *createTCPProcessor(const char *addr_str) { string addr; if (addr_str) addr = addr_str; if (addr.length() <= 4) return NULL; if (addr.substr(0, 4) != "tcp:") return NULL; #ifdef WIN32 WSADATA wsaData; WSAStartup(WS_VERSION_REQD, &wsaData); #endif int s = socket(AF_INET, SOCK_STREAM, 0); if (s != -1){ sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = 0; socklen_t addr_len = sizeof(addr); if (bind(s, (sockaddr*)&addr, addr_len) == -1){ #ifdef WIN32 closesocket(s); #else close(s); #endif s = -1; } } if (s != -1){ addr = addr.substr(4); string host; unsigned port; int n = addr.find(':'); if (n > 0){ host = addr.substr(0, n); port = atol(addr.substr(n + 1).c_str()); }else{ port = atol(addr.c_str()); } in_addr_t ip = INADDR_NONE; if (port){ if (!host.empty()){ ip = inet_addr(host.c_str()); hostent *h = gethostbyname(host.c_str()); if (h) ip = *((int*)(*(h->h_addr_list))); }else{ ip = inet_addr("127.0.0.1"); } } if (ip == INADDR_NONE){ #ifdef WIN32 closesocket(s); #else close(s); #endif s = -1; }else{ sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = ip; addr.sin_port = htons(port); socklen_t addr_len = sizeof(addr); if (connect(s, (sockaddr*)&addr, addr_len) == -1){ #ifdef WIN32 closesocket(s); #else close(s); #endif s = -1; } } } return new SocketProcessor(s); } #ifdef WIN32 #include #include extern CComModule _Module; #include #include class AutoProcessor : public Processor { public: AutoProcessor(); virtual bool process(const char *in_str, string &out_str); protected: CComDispatchDriver disp; }; AutoProcessor::AutoProcessor() { CoInitialize(NULL); CLSID clsid; HRESULT hResult; hResult = CLSIDFromProgID(L"Simremote.SimControl", &clsid); if (FAILED(hResult)) return; CComPtr pUnk; hResult = pUnk.CoCreateInstance(clsid); if (FAILED(hResult)) return; disp = pUnk; bInit = true; } bool AutoProcessor::process(const char *in_str, string &out_str) { if (!bInit) return false; CComBSTR str(in_str); CComVariant vArg(str); CComVariant vRes; HRESULT hResult = disp.Invoke1(L"Process", &vArg, &vRes); if (FAILED(hResult)) return false; CComBSTR out(vRes.bstrVal); if (out.Length()){ size_t size = WideCharToMultiByte(CP_ACP, 0, out, wcslen(out), 0, 0, NULL, NULL); char *res = new char[size + 1]; size = WideCharToMultiByte(CP_ACP, 0, out, wcslen(out), res, size, NULL, NULL); res[size] = 0; out_str = res; delete[] res; }else{ return false; } return true; } Processor *createProcessor(const char *addr_str) { Processor *processor = createTCPProcessor(addr_str); if (processor) return processor; string addr; if (addr_str) addr = addr_str; if (addr.empty()) addr = "auto:"; int n = addr.find(':'); if (n < 0) return NULL; string proto = addr.substr(0, n); addr = addr.substr(n + 1); if (proto == "auto") return new AutoProcessor; return NULL; } #else Processor *createProcessor(const char *addr_str) { Processor *processor = createTCPProcessor(addr_str); if (processor != NULL) return processor; string addr = "/tmp/sim.%user%"; if (addr_str) addr = addr_str; int n = addr.find("%user%"); if (n >= 0){ uid_t uid = getuid(); struct passwd *pwd = getpwuid(uid); string user; if (pwd){ user = pwd->pw_name; }else{ char b[32]; sprintf(b, "%u", uid); user = b; } addr = addr.substr(0, n) + user + addr.substr(n + 6); } int s = socket(PF_UNIX, SOCK_STREAM, 0); if (s < 0){ fprintf(stderr, "Can't create socket: %s\n", strerror(errno)); return NULL; } char local_name[256]; strcpy(local_name, "/tmp/sim.XXXXX"); mkstemp(local_name); if (local_name == NULL) return NULL; struct sockaddr_un sun_local; sun_local.sun_family = AF_UNIX; strcpy(sun_local.sun_path, local_name); unlink(local_name); if (bind(s, (struct sockaddr*)&sun_local, sizeof(sun_local)) < 0){ fprintf(stderr, "Can't bind socket %s: %s\n", local_name, strerror(errno)); return NULL; } struct sockaddr_un sun_remote; sun_remote.sun_family = AF_UNIX; strcpy(sun_remote.sun_path, addr.c_str()); if (connect(s, (struct sockaddr*)&sun_remote, sizeof(sun_remote)) < 0){ fprintf(stderr, "Can't connect to %s: %s\n", addr.c_str(), strerror(errno)); unlink(local_name); return NULL; } unlink(local_name); return new SocketProcessor(s); } #endif static void usage(char *s) { #ifndef WIN32 uid_t uid = getuid(); struct passwd *pwd = getpwuid(uid); char uid_buf[256]; char *name = NULL; if (pwd){ name = pwd->pw_name; }else{ snprintf(uid_buf, sizeof(uid_buf), "%u", uid); name = uid_buf; } #endif fprintf(stderr, "usage: %s [options] [uin files]\n" "Options are: [followed by default value]:\n" #ifndef WIN32 " -s socket [/tmp/sim.%s] Control socket\n" #endif // " -d Debug mode\n" " -c command Command\n" " -h Show this help\n" "\n", s #ifndef WIN32 ,name #endif ); } int main(int, char **argv) { list uins; const char *cmd = NULL; const char *addr = NULL; for (char **p = argv + 1; *p; p++){ if (!strcmp(*p, "-h")){ usage(argv[0]); return 0; } if (!strcmp(*p, "-s")){ p++; if (*p == NULL){ usage(argv[0]); return 1; } addr = *p; continue; } if (!strcmp(*p, "-c")){ p++; if (*p == NULL){ usage(argv[0]); return 1; } cmd = *p; continue; } uins.push_back(*p); } auto_ptr processor(createProcessor(addr)); if ((processor.get() == NULL) || !processor->bInit){ fprintf(stderr, "Can't create processor\n"); return 1; } if (uins.size()){ for (list::iterator it = uins.begin(); it != uins.end(); ++it){ string in_str; in_str = "FILE \""; in_str += *it; in_str += "\""; string out_str; if (!processor->process(in_str.c_str(), out_str)) break; } return 0; } if (cmd){ string out_str; if (!processor->process(cmd, out_str)){ fprintf(stderr, "Can't execute %s\n", cmd); exit(1); } if (out_str.empty()){ fprintf(stderr, "No answer\n"); exit(1); } if (out_str[0] != '>'){ fprintf(stderr, "Execute %s fail\n", cmd); exit(1); } printf("%s\n", out_str.c_str() + 1); exit(0); } FILE *f = stdin; while (!feof(f) && !ferror(f)){ printf(">"); char buf[4096]; char *line = fgets(buf, sizeof(buf), f); if (line == NULL) break; if (strlen(line) && (line[strlen(line) - 1] == '\n')) line[strlen(line) - 1] = 0; if (strlen(line) && (line[strlen(line) - 1] == '\r')) line[strlen(line) - 1] = 0; string out_str; if (!processor->process(line, out_str)) break; if (out_str.empty()) break; bool bBad = (out_str[0] == '?'); out_str = out_str.substr(1); if (bBad) printf("? "); printf("%s\n", out_str.c_str()); } return 0; }