You can use this quick&dirty piece of software listed below to
redirect std i/o of a program to a tcp connection.

Assuming the executable file is named tcpcmd.exe. Following command line
   tcpcmd 12345 "sqlite3 -batch"
will run "sqlite3 -batch" and listen on tcp port 12345 (for security
reasons it listens only on loopback interface (127.0.0.1)).

(You may need to link with ws2_32.lib)
-------------------------------------------------------------------------
#include <WinSock2.h>
#include <stdio.h>

#define BUFFER_SIZE 1024
#define OV_ENTRIES 2

enum TransferState
{
        TS_NULL,
        TS_READING,
        TS_READY,
        TS_WRITING
};

WSADATA g_WsaData;
PROCESS_INFORMATION g_Process;
SOCKET g_sockLst, g_sockClient;
HANDLE g_hInWr, g_hInRd, g_hOutWr, g_hOutRd;
HANDLE g_hIOCP;
wchar_t* g_zCommand;
int g_nPort;
int g_bConnected = 0;
enum TransferState g_eInState = TS_NULL, g_eOutState = TS_NULL;
OVERLAPPED g_ovIn, g_ovOut;
WSABUF g_wbIn, g_wbOut;
DWORD g_flgWsaIn;
DWORD g_nIn, g_nOut;
char g_bufIn[BUFFER_SIZE], g_bufOut[BUFFER_SIZE];

void printError(const wchar_t* zFunc, DWORD nErr);
int parseArgs(int argc, wchar_t* argv[]);
int openPort();
int acceptClient();
void closeClient();
int runCommandProcess();
int main_loop();

int wmain(int argc, wchar_t* argv[])
{
        int rc = parseArgs(argc, argv);
        if (rc)
                return rc;
        rc = WSAStartup(MAKEWORD(2, 2), &g_WsaData);
        if (rc)
        {
                printError(L"WSAStartup", rc);
                return rc;
        }
        rc = openPort();
        if (!rc)
        {
                rc = runCommandProcess();
                if (!rc)
                {
                        while (main_loop() == 0);
                        TerminateProcess(g_Process.hProcess, 0);
                }
                closeClient();
                closesocket(g_sockLst);
        }
        WSACleanup();
        return rc;
}

int main_loop()
{
        int rc;
        DWORD dwProcExit;
        ULONG i;
        ULONG nOvEntries = 0;
        OVERLAPPED_ENTRY ovEntries[OV_ENTRIES];
        rc = GetExitCodeProcess(g_Process.hProcess, &dwProcExit);
        if (!rc)
        {
                printError(L"GetExitCodeProcess", GetLastError());
                return 1;
        }
        if (dwProcExit != STILL_ACTIVE)
                return 1;
        switch (g_eInState)
        {
        case TS_NULL:
                rc = acceptClient();
                if (rc)
                        break;
                memset(&g_ovIn, 0, sizeof(g_ovIn));
                g_wbIn.buf = g_bufIn;
                g_wbIn.len = BUFFER_SIZE;
                g_nIn = 0;
                g_flgWsaIn = 0;
                rc = WSARecv(g_sockClient, &g_wbIn, 1, NULL, &g_flgWsaIn, 
&g_ovIn, NULL);
                if (rc)
                {
                        DWORD err = WSAGetLastError();
                        if (err != ERROR_IO_PENDING)
                        {
                                printError(L"WSARecv", err);
                                closeClient();
                                return 0;
                        }
                }
                g_eInState = TS_READING;
                break;
        case TS_READY:
                memset(&g_ovIn, 0, sizeof(g_ovIn));
                rc = WriteFile(g_hInWr, g_bufIn, g_nIn, NULL, &g_ovIn);
                if (!rc)
                {
                        DWORD err = GetLastError();
                        if (err != ERROR_IO_PENDING)
                        {
                                printError(L"WriteFile", err);
                                return 1;
                        }
                }
                g_eInState = TS_WRITING;
                break;
        default:
                break;
        }
        switch (g_eOutState)
        {
        case TS_NULL:
                memset(&g_ovOut, 0, sizeof(g_ovOut));
                rc = ReadFile(g_hOutRd, g_bufOut, BUFFER_SIZE, NULL, &g_ovOut);
                if (!rc)
                {
                        DWORD err = GetLastError();
                        if (err != ERROR_IO_PENDING)
                        {
                                printError(L"ReadFile", err);
                                return 1;
                        }
                }
                g_eOutState = TS_READING;
                break;
        case TS_READY:
                rc = acceptClient();
                if (rc)
                        break;
                memset(&g_ovOut, 0, sizeof(g_ovOut));
                g_wbOut.buf = g_bufOut;
                g_wbOut.len = g_nOut;
                rc = WSASend(g_sockClient, &g_wbOut, 1, NULL, 0, &g_ovOut, 
NULL);
                if (rc)
                {
                        DWORD err = WSAGetLastError();
                        if (err != ERROR_IO_PENDING)
                        {
                                printError(L"WSASend", err);
                                closeClient();
                                return 0;
                        }
                }
                g_eOutState = TS_WRITING;
                break;
        default:
                break;
        }
        memset(&ovEntries, 0, sizeof(ovEntries));
        rc = GetQueuedCompletionStatusEx(g_hIOCP, ovEntries, 2, &nOvEntries,
10000, TRUE);
        if (!rc)
                return 0;
        for (i = 0; i < nOvEntries; ++i)
        {
                LPOVERLAPPED_ENTRY pOvEn = &ovEntries[i];
                if (pOvEn->lpOverlapped == &g_ovIn)
                {
                        switch (g_eInState)
                        {
                        case TS_READING:
                                g_nIn = pOvEn->dwNumberOfBytesTransferred;
                                if (g_nIn)
                                        g_eInState = TS_READY;
                                else
                                {
                                        g_eInState = TS_NULL;
                                        closeClient();
                                }
                                break;
                        case TS_WRITING:
                                if (g_nIn <= pOvEn->dwNumberOfBytesTransferred)
                                        g_eInState = TS_NULL;
                                else
                                {
                                        g_nIn -= 
pOvEn->dwNumberOfBytesTransferred;
                                        memmove(g_bufIn, (g_bufIn + 
pOvEn->dwNumberOfBytesTransferred), g_nIn);
                                        g_eInState = TS_READY;
                                }
                                break;
                        default:
                                break;
                        }
                }
                else if (pOvEn->lpOverlapped == &g_ovOut)
                {
                        switch (g_eOutState)
                        {
                        case TS_READING:
                                g_nOut = pOvEn->dwNumberOfBytesTransferred;
                                if (g_nOut)
                                        g_eOutState = TS_READY;
                                else
                                        g_eOutState = TS_NULL;
                                break;
                        case TS_WRITING:
                                if (g_nOut <= pOvEn->dwNumberOfBytesTransferred)
                                        g_eOutState = TS_NULL;
                                else
                                {
                                        g_nOut -= 
pOvEn->dwNumberOfBytesTransferred;
                                        memmove(g_bufOut, (g_bufOut + 
pOvEn->dwNumberOfBytesTransferred), g_nOut);
                                        g_eOutState = TS_READY;
                                }
                                break;
                        default:
                                break;
                        }
                }
        }
        return 0;
}

int openPort()
{
        int rc;
        struct sockaddr_in saddrLst;
        g_sockLst = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (g_sockLst == INVALID_SOCKET)
        {
                printError(L"socket", WSAGetLastError());
                return 1;
        }
        memset(&saddrLst, 0, sizeof(saddrLst));
        saddrLst.sin_family = AF_INET;
        saddrLst.sin_port = htons(g_nPort);
        saddrLst.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
        rc = bind(g_sockLst, (struct sockaddr*)&saddrLst, sizeof(saddrLst));
        if (rc)
        {
                printError(L"bind", WSAGetLastError());
                closesocket(g_sockLst);
                return rc;
        }
        rc = listen(g_sockLst, 1);
        if (rc)
        {
                printError(L"listen", WSAGetLastError());
                closesocket(g_sockLst);
                return rc;
        }
        return rc;
}

int acceptClient()
{
        HANDLE hIOCP;
        if (g_bConnected)
                return 0;
        g_sockClient = accept(g_sockLst, NULL, NULL);
        if (g_sockClient == INVALID_SOCKET)
        {
                printError(L"accept", WSAGetLastError());
                return 1;
        }
        hIOCP = CreateIoCompletionPort((HANDLE)g_sockClient, g_hIOCP, 0, 0);
        if (!hIOCP)
        {
                printError(L"CreateIoCompletionPort", GetLastError());
                closesocket(g_sockClient);
                return 1;
        }
        g_bConnected = 1;
        return 0;
}

void closeClient()
{
        if (g_bConnected)
                closesocket(g_sockClient);
        g_bConnected = 0;
}

int createPipe(PHANDLE phServer, PHANDLE phClient, int dir)
{
        DWORD dwOpenMode = (dir ? PIPE_ACCESS_INBOUND : PIPE_ACCESS_OUTBOUND)
                | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED;
        DWORD dwFileAccess = (dir ? GENERIC_WRITE : GENERIC_READ);
        DWORD dwFileShare = (dir ? FILE_SHARE_READ : FILE_SHARE_WRITE)
                | FILE_SHARE_DELETE;
        SECURITY_ATTRIBUTES sec_attr;
        wchar_t name[256];
        swprintf(name, 255, L"\\\\.\\pipe\\ChildStdPipe%d_P%u_T%u", dir,
GetCurrentProcessId(), GetCurrentThreadId());
        *phServer = CreateNamedPipeW(name, dwOpenMode,
PIPE_REJECT_REMOTE_CLIENTS, 1, 0, 0, 0, NULL);
        if (*phServer == INVALID_HANDLE_VALUE)
        {
                printError(L"CreateNamedPipeW", GetLastError());
                return 1;
        }
        memset(&sec_attr, 0, sizeof(sec_attr));
        sec_attr.bInheritHandle = TRUE;
        *phClient = CreateFileW(name, dwFileAccess, dwFileShare, &sec_attr,
OPEN_EXISTING, 0, NULL);
        if (*phClient == INVALID_HANDLE_VALUE)
        {
                printError(L"CreateFileW", GetLastError());
                CloseHandle(*phServer);
                return 1;
        }
        return 0;
}

int runCommandProcess()
{
        int rc;
        
        STARTUPINFOW startup_info;
        memset(&startup_info, 0, sizeof(startup_info));
        rc = createPipe(&g_hInWr, &g_hInRd, 0);
        if (rc)
                return rc;
        rc = createPipe(&g_hOutRd, &g_hOutWr, 1);
        if (rc)
                return rc;
        g_hIOCP = CreateIoCompletionPort(g_hInWr, NULL, 0, 0);
        if (!g_hIOCP)
        {
                printError(L"CreateIoCompletionPort", GetLastError());
                return 1;
        }
        g_hIOCP = CreateIoCompletionPort(g_hOutRd, g_hIOCP, 0, 0);
        if (!g_hIOCP)
        {
                printError(L"CreateIoCompletionPort", GetLastError());
                return 1;
        }
        startup_info.cb = sizeof(startup_info);
        startup_info.dwFlags = STARTF_USESTDHANDLES;
        startup_info.hStdInput = g_hInRd;
        startup_info.hStdOutput = g_hOutWr;
        startup_info.hStdError = g_hOutWr;
        rc = CreateProcessW(NULL, g_zCommand, NULL, NULL, TRUE,
                CREATE_UNICODE_ENVIRONMENT, NULL, NULL, &startup_info, 
&g_Process);
        if (!rc)
        {
                printError(L"CreateProcess", GetLastError());
                return 1;
        }
        return 0;
}

void printError(const wchar_t* zFunc, DWORD nErr)
{
        static const DWORD fmtFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER
                | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
        LPWSTR zErr = NULL;
        FormatMessageW(fmtFlags, NULL, nErr, 0, (LPWSTR)&zErr, 0, NULL);
        fwprintf(stderr, L"%ls error (%u): %ls\n", zFunc, nErr, zErr);
        LocalFree((HLOCAL)zErr);
}

int parseArgs(int argc, wchar_t* argv[])
{
        static const wchar_t* const zUsage = L"Usage %ls <port> <command>";
        if (argc != 3)
        {
                fwprintf(stderr, zUsage, argv[0]);
                return 1;
        }
        g_nPort = wcstol(argv[1], NULL, 0);
        if (g_nPort < 1 || g_nPort > 65535)
        {
                fwprintf(stderr, L"Invalid port number %d\n", g_nPort);
                fwprintf(stderr, zUsage, argv[0]);
                return 1;
        }
        g_zCommand = argv[2];
        return 0;
}
-------------------------------------------------------------------------

2018-06-08 19:26 GMT+02:00, lhelger...@surplushunter.net
<lhelger...@surplushunter.net>:
>
>  Hello -
>
> I've been following for a while, a lot of very intelligent
> people here, and not a lot of fuss!!! Very nice, my compliments to
> all!!
>
> I'm just learning SQLite and using it to collect alarm values from a
> monitoring system. The monitoring system can't access the SQLite file
> directly, so I've been using sqlite3.exe as the intermediate.
>
> Since I'm
> making many access to the database the monitoring program is constantly
> launching sqlite3.exe with new commands or files of commands, very wasteful
> of resources. (Windows 7)
>
> Is there a platform/program that can be run as a
> SQLite "front end" that could be launched once and take commands from
> another program and pass back results, or is there a way to do that with
> sqlite3.exe? I've looked around the web and not found anything, so
> far.
>
> Any guidance is greatly appreciated, thanks for your time!!
>
> Leland
>
> _______________________________________________
> sqlite-users mailing list
> sqlite-users@mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>
_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to