From: <ped...@us...> - 2007-06-10 07:47:23
|
Revision: 934 http://svn.sourceforge.net/cegcc/?rev=934&view=rev Author: pedroalves Date: 2007-06-09 10:47:55 -0700 (Sat, 09 Jun 2007) Log Message: ----------- Adding PipeLib's device, lib and testers. Added Paths: ----------- trunk/cegcc/tools/PipeLib/ trunk/cegcc/tools/PipeLib/PipeDev/ trunk/cegcc/tools/PipeLib/PipeDev/Makefile trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h trunk/cegcc/tools/PipeLib/PipeLib/ trunk/cegcc/tools/PipeLib/PipeLib/Makefile trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h trunk/cegcc/tools/PipeLib/PipeTest/ trunk/cegcc/tools/PipeLib/PipeTest/Makefile trunk/cegcc/tools/PipeLib/PipeTest/PipeTest.cpp trunk/cegcc/tools/PipeLib/TestClient/ trunk/cegcc/tools/PipeLib/TestClient/Makefile trunk/cegcc/tools/PipeLib/TestClient/TestClient.cpp Added: trunk/cegcc/tools/PipeLib/PipeDev/Makefile =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/Makefile (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeDev/Makefile 2007-06-09 17:47:55 UTC (rev 934) @@ -0,0 +1,20 @@ +TARGET=arm-wince-mingw32ce + +CXX=$(TARGET)-g++ +AR=$(TARGET)-ar + +WARNFLAGS=-Wall -Wextra + +INCLUDES= + +ALLFLAGS=$(INCLUDES) $(CXXFLAGS) $(WARNFLAGS) + +all: PipeDev.dll + +PipeDev.dll: PipeDevice.cpp + $(CXX) $< -shared -o $@ $(ALLFLAGS) + +clean: + rm -f PipeDev.dll + +.PHONE: all clean Property changes on: trunk/cegcc/tools/PipeLib/PipeDev/Makefile ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-09 17:47:55 UTC (rev 934) @@ -0,0 +1,911 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "PipeDevice.h" + +#include <windows.h> +#include <devload.h> +#include <set> +#include <string> + +#ifndef min +#define min(A, B) ((A) < (B) ? (A) : (B)) +#endif + +typedef struct _DEVICE_PSL_NOTIFY +{ + DWORD dwSize; + DWORD dwFlags; + HANDLE hProc; + HANDLE hThread; +} DEVICE_PSL_NOTIFY, *PDEVICE_PSL_NOTIFY; + +#ifndef FILE_DEVICE_PSL +#define FILE_DEVICE_PSL 259 +#endif + +#define IOCTL_PSL_NOTIFY \ + CTL_CODE (FILE_DEVICE_PSL, 255, METHOD_NEITHER, FILE_ANY_ACCESS) + +#define DLL_PROCESS_EXITING 4 + +#define PIPEDEV_API extern "C" __declspec (dllexport) + +//#define DEBUG_MODE +//#define NOLOCKS +//#define DEBUG_LOCKS + +#ifdef DEBUG_LOCKS +# define G(CS) (__LINE__, CS) +#else +# define G(CS) (CS) +#endif + +class CSWrapper +{ +public: + explicit CSWrapper (CRITICAL_SECTION* cs) : cs_(*cs) {} + ~CSWrapper () {} + + void Lock () + { +#ifndef NOLOCKS + EnterCriticalSection (&cs_); +#endif + } + void Unlock () + { +#ifndef NOLOCKS + LeaveCriticalSection (&cs_); +#endif + } +private: + CRITICAL_SECTION& cs_; +}; + +class CS : public CSWrapper +{ +public: + CS () : CSWrapper (&cs_) + { +#ifndef NOLOCKS + InitializeCriticalSection (&cs_); +#endif + } + ~CS () + { +#ifndef NOLOCKS + DeleteCriticalSection (&cs_); +#endif + } +private: + CRITICAL_SECTION cs_; +}; + +class FastCS +{ +public: + FastCS () : Count(0) + { +#ifndef NOLOCKS + /* auto - only release one at a time. */ + EventHandle = CreateEvent (NULL, FALSE, FALSE, NULL); +#endif + } + ~FastCS () + { +#ifndef NOLOCKS + CloseHandle (EventHandle); +#endif + } + + void Lock () + { +#ifndef NOLOCKS + if (InterlockedIncrement (&Count) == 1) + /* first come - first serve. */ + return; + + /* everyone else, get in line. */ + WaitForSingleObject (EventHandle, INFINITE); +#endif + } + void Unlock () + { +#ifndef NOLOCKS + if (InterlockedDecrement (&Count) > 0) + /* release one pending */ + SetEvent (EventHandle); +#endif + } +private: + HANDLE EventHandle; + LONG Count; +}; + +class RecursiveCS +{ +public : + RecursiveCS () + : Count(0) + , RecursionCount(0) + , ThreadID(0) + + { +#ifndef NOLOCKS + /* auto - only release one at a time. */ + EventHandle = CreateEvent (NULL, FALSE, FALSE, NULL); +#endif + } + + ~RecursiveCS () + { +#ifndef NOLOCKS + CloseHandle (EventHandle); +#endif + } + + void Lock () + { +#ifndef NOLOCKS + if (ThreadID == GetCurrentThreadId ()) + { + InterlockedIncrement (&RecursionCount); + return; + } + + if (InterlockedIncrement (&Count) == 1) + InterlockedExchange (&RecursionCount, 0); + else + WaitForSingleObject (EventHandle, INFINITE); + + ThreadID = GetCurrentThreadId (); +#endif + } + + void Unlock () + { +#ifndef NOLOCKS + if (RecursionCount == 0) + { + if (InterlockedDecrement (&Count) > 0) + { + /* release one thread */ + SetEvent (EventHandle); + } + } + else + { + InterlockedDecrement (&RecursionCount); + } +#endif + } + +private: + HANDLE EventHandle; + LONG Count; + LONG RecursionCount; + DWORD ThreadID; +}; + + +template <class T> +class LockGuard +{ +public: +#ifdef DEBUG_LOCKS + LockGuard (int line, T &cs) : cs_(cs), lineno(line) + { + WCHAR buf[100]; + wsprintf (buf, L"line : %d", line); + MessageBoxW(0, buf, L"lock", 0); + + cs_.Lock (); + } + ~LockGuard () + { + WCHAR buf[100]; + wsprintf (buf, L"line : %d", lineno); + MessageBoxW(0, buf, L"unlock", 0); + + cs_.Unlock (); + } +#else + explicit LockGuard (T &cs) : cs_(cs) { cs_.Lock (); } + ~LockGuard () { cs_.Unlock (); } +#endif + +private: + T &cs_; + +#ifdef DEBUG_LOCKS + int lineno; +#endif +}; + +class PipeOpenContext; + +class PipeDeviceContext +{ +public: + typedef ::LockGuard<PipeDeviceContext> LockGuard; + + explicit PipeDeviceContext (LPCWSTR activepath) + : OpenCount(0) + , WROpenCount(0) + , DeviceName(NULL) + , Aborting(FALSE) + , head(0) + , count(0) + { + ActivePath = wcsdup (activepath); + ReadEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + WriteEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + + /* This should wake all threads, so it is manual reset. */ + AbortEvent = CreateEvent (NULL, TRUE, FALSE, NULL); + } + + ~PipeDeviceContext () + { + if (DeviceName) + free (DeviceName); + if (ActivePath) + free (ActivePath); + CloseHandle (ReadEvent); + CloseHandle (WriteEvent); + CloseHandle (AbortEvent); + } + + DWORD size () + { + return count; + } + + DWORD tail () + { + return (head + count) & (sizeof (buffer) - 1); + } + + void Lock () + { + cs.Lock (); + } + + void Unlock () + { + cs.Unlock (); + } + + DWORD writeBytes (const void* data_, DWORD dsize) + { + DWORD fit = sizeof (buffer) - size (); + fit = min (dsize, fit); + const BYTE* data = (const BYTE*)data_; + BYTE* b = buffer + tail (); + for (DWORD i = 0; i < fit; i++) + b[i & (sizeof (buffer) - 1)] = data[i]; + count += fit; + return fit; + } + + DWORD readBytes (void* buf_, DWORD bsize) + { + BYTE* buf = (BYTE*)buf_; + DWORD fit = min (bsize, size ()); + + const BYTE* h = buffer + head; + for (DWORD i = 0; i < fit; i++) + buf[i] = h[i & (sizeof (buffer) - 1)]; + count -= fit; + head += fit; + head &= (sizeof (buffer) - 1); + return fit; + } + +public: + DWORD OpenCount; + DWORD WROpenCount; + + WCHAR* ActivePath; + + HANDLE ReadEvent; + HANDLE WriteEvent; + HANDLE AbortEvent; + + WCHAR* DeviceName; + BOOL Aborting; + +private: + BYTE buffer[0x1000]; + DWORD head; + DWORD count; + + RecursiveCS cs; +}; + +class PipeOpenContext +{ +public: + PipeOpenContext (PipeDeviceContext* devctx, + DWORD accessCode, DWORD shareMode) + : DeviceContext (devctx) + , dwAccessCode (accessCode) + , dwShareMode (shareMode) + {} + + ~PipeOpenContext () + {} + + PipeDeviceContext* DeviceContext; + DWORD dwAccessCode; + DWORD dwShareMode; +}; + +static CRITICAL_SECTION open_pipes_cs; + +extern "C" BOOL WINAPI +DllMain (HANDLE /*hinstDLL*/, DWORD dwReason, LPVOID /*lpvReserved*/) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + InitializeCriticalSection (&open_pipes_cs); + break; + case DLL_PROCESS_DETACH: + DeleteCriticalSection (&open_pipes_cs); + break; + } + + return TRUE; +} + +static void +LogMessage (const char* msg, ...) +{ +#if 0 + va_list ap; + va_start (ap, msg); + FILE* log = fopen ("log.txt", "a+"); + vfprintf (log, msg, ap); + fclose (log); + va_end (ap); +#else + (void)msg; +#endif +} + +struct LogScope +{ + explicit LogScope (const char* func) + : func_(func) + { + LogMessage ("entering %s\n", func_); + } + ~LogScope () + { + LogMessage ("leaving %s\n", func_); + } + + const char* func_; +}; + +#define LOGSCOPE(MSG) LogScope scope ## __LINE__(#MSG) + +/* This is needed for MSVC. */ +struct ltwstr +{ + bool operator () (const std::wstring& s1, const std::wstring& s2) const + { + return wcscmp (s1.c_str (), s2.c_str ()) < 0; + } +}; + +typedef std::set<std::wstring, ltwstr> vwstring; +static vwstring open_pipes; + +PIPEDEV_API BOOL Deinit (PipeDeviceContext* pDeviceContext); + +static HANDLE +GetDeviceHandle (PipeDeviceContext* pDeviceContext) +{ + LOGSCOPE (GetDeviceHandle); + HKEY hActive; + DWORD Type; + HANDLE hDev = INVALID_HANDLE_VALUE; + + DWORD status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, pDeviceContext->ActivePath, + 0, 0, &hActive); + if (status != ERROR_SUCCESS) + return INVALID_HANDLE_VALUE; + + DWORD Len = sizeof(hDev); + status = RegQueryValueEx (hActive, DEVLOAD_HANDLE_VALNAME, NULL, &Type, + (PUCHAR)&hDev, &Len); + if (status != ERROR_SUCCESS) + { + /* weird */ + } + + RegCloseKey (hActive); + + return hDev; +} + +PIPEDEV_API DWORD +Init (LPCTSTR pContext) +{ + LOGSCOPE ("Init"); + CSWrapper cs (&open_pipes_cs); + LockGuard<CSWrapper> guard G(cs); + +#ifdef DEBUG_MODE + MessageBoxW (0, pContext, L"Init", 0); +#endif + + /* TODO: The key here isn't exactly the best. Maybe we should use + the device name instead, and get that from the registry - that would + also get rid of the IOCTL calls. */ + if (open_pipes.find (pContext) != open_pipes.end ()) + /* already open, PipeLib will try another one. */ + return 0; + + PipeDeviceContext* pDeviceContext = new PipeDeviceContext (pContext); + if (pDeviceContext == NULL) + return 0; + + open_pipes.insert (pContext); + + return (DWORD)pDeviceContext; +} + +#ifdef DEBUG_MODE +static int close_calls; +#endif + +PIPEDEV_API BOOL +Deinit (PipeDeviceContext* pDeviceContext) +{ + LOGSCOPE ("Deinit"); + /* All file handles must to be closed before deinitialising + the driver. */ + +#ifdef DEBUG_MODE + WCHAR buf[100]; + wsprintf (buf, L"opencount %d : calls %d", pDeviceContext->OpenCount, + close_calls); + MessageBoxW (0, buf, L"Deinit", 0); +#endif + + if (pDeviceContext == NULL) + return FALSE; + + { + PipeDeviceContext::LockGuard guard G(*pDeviceContext); + + if (pDeviceContext->OpenCount != 0) + return FALSE; + } + +#ifdef DEBUG_MODE + MessageBoxW (0, L"deactivate success", L"Deinit", 0); +#endif + + /* Allow reuse. */ + open_pipes.erase (pDeviceContext->ActivePath); + + /* Race? Is it possible that there can be another process + calling any function on the device while we are + Dinitializing it? Doesn't CE take care of that? */ + delete pDeviceContext; + return TRUE; +} + +PIPEDEV_API DWORD +Open (PipeDeviceContext* pDeviceContext, DWORD AccessCode, DWORD ShareMode) +{ + LOGSCOPE ("Open"); + +#ifdef DEBUG_MODE + wchar_t buf[100]; + wsprintf (buf, L"opencount %d", pDeviceContext->OpenCount); + MessageBoxW (0, buf, L"open 1", 0); +#endif + + PipeOpenContext* pOpenContext = + new PipeOpenContext (pDeviceContext, AccessCode, ShareMode); + +#ifdef DEBUG_MODE + MessageBoxW (0, L"going to lock", L"open 2", 0); +#endif + + PipeDeviceContext::LockGuard guard G(*pOpenContext->DeviceContext); + +#ifdef DEBUG_MODE + MessageBoxW (0, L"locked", L"open 3", 0); +#endif + + pDeviceContext->OpenCount++; + + if (AccessCode & GENERIC_WRITE) + pDeviceContext->WROpenCount++; + +#ifdef DEBUG_MODE + wsprintf (buf, L"opencount %d", pDeviceContext->OpenCount); + MessageBoxW (0, buf, L"open", 0); +#endif + + return (DWORD)pOpenContext; +} + +struct DeactivatorData +{ + HANDLE th; + HANDLE dev; +}; + +static DWORD WINAPI +Deactivator (void* arg) +{ + LOGSCOPE ("Deactivator"); + + DeactivatorData* data = (DeactivatorData*)arg; + +#ifdef DEBUG_MODE + wchar_t buf[100]; + wsprintf (buf, L"%x", data->dev); + MessageBoxW(0, buf, L"close: dev handle", 0); + if (!DeactivateDevice (data->dev)) + MessageBoxW(0, buf, L"deactivate failed", 0); + else + MessageBoxW(0, buf, L"after deactivate", 0); +#else + DeactivateDevice (data->dev); +#endif + + CloseHandle (data->th); + delete data; + + return 0; +} + +static void +DeactivatePipeDevice (PipeDeviceContext* dev) +{ + LOGSCOPE ("DeactivatePipeDevice"); + + HANDLE hdev = GetDeviceHandle (dev); + DeactivatorData* data = new DeactivatorData (); + data->dev = hdev; + data->th = CreateThread (NULL, 0, Deactivator, data, + CREATE_SUSPENDED, NULL); + ResumeThread (data->th); +} + +PIPEDEV_API BOOL +Close (PipeOpenContext* pOpenContext) +{ + LOGSCOPE ("Close"); +#ifdef DEBUG_MODE + close_calls++; + + wchar_t buf[100]; + if (pOpenContext) + { + wsprintf (buf, L"opencount %d : %p", + pOpenContext->DeviceContext->OpenCount, + pOpenContext); + MessageBoxW (0, buf, L"close", 0); + } + else + { + wsprintf (buf, L"openctx %p", pOpenContext); + MessageBoxW (0, buf, L"close", 0); + } +#endif + + if (pOpenContext == NULL) + return FALSE; + + PipeDeviceContext* dev = pOpenContext->DeviceContext; + + PipeDeviceContext::LockGuard guard G(*dev); + + if (dev->OpenCount == 0) + return FALSE; + + dev->OpenCount--; + + if (pOpenContext->dwAccessCode & GENERIC_WRITE) + { + dev->WROpenCount--; + if (dev->WROpenCount == 0) + /* Wake up the reading side so it can see + the broken pipe. */ + SetEvent (dev->AbortEvent); + } + + delete pOpenContext; + +#ifdef DEBUG_MODE + wsprintf (buf, L"opencount %d", dev->OpenCount); + MessageBoxW (0, buf, L"close 2", 0); +#endif + + if (dev->OpenCount == 0) + { +#if 0 + HANDLE hdev = GetDeviceHandle (dev); + DeactivateDevice (hdev); +#else + DeactivatePipeDevice (dev); +#endif + } + + return TRUE; +} + +PIPEDEV_API DWORD +Read (PipeOpenContext* pOpenContext, LPVOID pBuffer_, DWORD dwCount) +{ + LOGSCOPE ("Read"); + + if (IsBadReadPtr (pBuffer_, dwCount)) + { + SetLastError (ERROR_INVALID_PARAMETER); + return -1; + } + + BYTE* pBuffer = (BYTE*)pBuffer_; + DWORD needed = dwCount; + + if (pOpenContext == NULL + || (pOpenContext->dwAccessCode & GENERIC_READ) == 0) + return (DWORD)-1; + + PipeDeviceContext* dev = pOpenContext->DeviceContext; + + BOOL breaknext = FALSE; + HANDLE Events[2]; + + do + { + { + PipeDeviceContext::LockGuard guard G(*dev); + + Events[0] = dev->WriteEvent; + Events[1] = dev->AbortEvent; + + if (dev->Aborting) + /* this device is long gone */ + return (DWORD)-1; + + if (dev->WROpenCount == 0) + /* broken pipe */ + return (DWORD)-1; + + if (dev->OpenCount == 0) + /* weird */ + return (DWORD)-1; + + DWORD read = dev->readBytes (pBuffer, dwCount); + pBuffer += read; + dwCount -= read; + + if (read) + SetEvent (dev->ReadEvent); + + if (dwCount == 0) + break; + + if (breaknext) + break; + } + + switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) + { + case WAIT_OBJECT_0: + breaknext = TRUE; + break; + default: + // MessageBoxW (0, L"pipe aborted", L"Read", 0); + /* With either wait error or AbortEvent + signaled, return with error. */ + return (DWORD)-1; + } + } + while (dwCount); + + return needed - dwCount; +} + +PIPEDEV_API DWORD +Write (PipeOpenContext* pOpenContext, LPCVOID pBuffer_, DWORD dwCount) +{ + LOGSCOPE ("Write"); + + if (IsBadReadPtr (pBuffer_, dwCount)) + { + SetLastError (ERROR_INVALID_PARAMETER); + return -1; + } + + const BYTE* pBuffer = (const BYTE*)pBuffer_; + DWORD needed = dwCount; + +#ifdef DEBUG_MODE + wchar_t buf[100]; + wsprintf (buf, L"opencount %d", pOpenContext->DeviceContext->OpenCount); + MessageBoxW (0, buf, L"write", 0); +#endif + + if (pOpenContext == NULL + || (pOpenContext->dwAccessCode & GENERIC_WRITE) == 0) + return (DWORD)-1; + + PipeDeviceContext* dev = pOpenContext->DeviceContext; + + BOOL breaknext = FALSE; + HANDLE Events[2]; + + do + { + { + PipeDeviceContext::LockGuard guard G(*dev); + +#ifdef DEBUG_MODE + MessageBoxW (0, L"lock acquired", L"write", 0); +#endif + + Events[0] = dev->ReadEvent; + Events[1] = dev->AbortEvent; + + if (dev->Aborting) + /* this device is long gone */ + return (DWORD)-1; + + if (dev->OpenCount == 0) + /* weird */ + return (DWORD)-1; + + /* According to MSDN, attempting to read from a pipe without writers, + generates a broken pipe error, but the opposite isn't forbidden, so we + allow writing to a pipe without a reader. */ + + DWORD wrote = dev->writeBytes (pBuffer, dwCount); + pBuffer += wrote; + dwCount -= wrote; + + /* According to MSDN, a write of 0, also wakes + the reading end of the pipe. */ + PulseEvent (dev->WriteEvent); + + if (dwCount == 0) + break; + + if (breaknext) + break; + } + + switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) + { + case WAIT_OBJECT_0: + breaknext = TRUE; + break; + default: + // MessageBoxW (0, L"pipe aborted", L"Write", 0); + /* With either wait error or AbortEvent + signaled, return with error. */ + return (DWORD) -1; + } + } + while (dwCount); + + return needed - dwCount; +} + +PIPEDEV_API DWORD +Seek (PipeOpenContext* /*pOpenContext*/, long /*Amount*/, WORD /*wType*/) +{ + LOGSCOPE ("Seek"); + /* Pipes don't support seeking. */ + return (DWORD)-1; +} + +PIPEDEV_API BOOL +IOControl (PipeOpenContext* pOpenContext, DWORD dwCode, + PBYTE pBufIn, DWORD dwLenIn, + PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut) +{ + LOGSCOPE ("IOControl"); + + /* Kill unused warnings. */ + (void)pBufIn; + (void)dwLenIn; + (void)pBufOut; + (void)dwLenOut; + (void)pdwActualOut; + + BOOL bRet = FALSE; + + if (pOpenContext == NULL) + return FALSE; + + PipeDeviceContext* dev = pOpenContext->DeviceContext; + PipeDeviceContext::LockGuard guard G(*dev); + +#ifdef DEBUG_MODE + wchar_t buf[100]; + wsprintf (buf, L"%x : %d", dwCode, dev->OpenCount); + MessageBoxW (0, buf, L"IOControl", 0); +#endif + + if (dwCode == IOCTL_PSL_NOTIFY) + { + PDEVICE_PSL_NOTIFY pPslPacket = (PDEVICE_PSL_NOTIFY)pBufIn; + + if (pPslPacket->dwSize == sizeof (DEVICE_PSL_NOTIFY) + && pPslPacket->dwFlags == DLL_PROCESS_EXITING) + { +#ifdef DEBUG_MODE + WCHAR buf[100]; + wsprintf (buf, L"%p : %p", pPslPacket->hProc, pPslPacket->hThread); + MessageBoxW(0, buf, L"process dying", 0); +#endif + dev->Aborting = TRUE; + /* Unlock all blocked threads. */ + SetEvent (dev->AbortEvent); + } + return TRUE; + } + + switch (dwCode) + { + case PIPE_IOCTL_SET_PIPE_NAME: + if (dev->DeviceName) + free (dev->DeviceName); + dev->DeviceName = wcsdup ((WCHAR*)pBufIn); + bRet = TRUE; + break; + case PIPE_IOCTL_GET_PIPE_NAME: + wcscpy ( (WCHAR*)pBufOut, dev->DeviceName); + *pdwActualOut = (wcslen (dev->DeviceName) + 1) * sizeof (WCHAR); + bRet = TRUE; + break; + } + + return bRet; +} + +PIPEDEV_API void +PowerDown (PipeDeviceContext* /*pDeviceContext*/) +{ +} + +PIPEDEV_API void +PowerUp (PipeDeviceContext* /*pDeviceContext*/) +{ +} Property changes on: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h 2007-06-09 17:47:55 UTC (rev 934) @@ -0,0 +1,41 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#ifndef __PIPEDEVICE_H__ +#define __PIPEDEVICE_H__ + +#include <windows.h> +#include <winioctl.h> + +#define PIPE_IOCTL_SET_PIPE_NAME \ + CTL_CODE(FILE_DEVICE_STREAMS, 2048, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define PIPE_IOCTL_GET_PIPE_NAME \ + CTL_CODE(FILE_DEVICE_STREAMS, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define DEVICE_DLL_NAME L"PipeDev.dll" + +#endif Property changes on: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/PipeLib/PipeLib/Makefile =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib/Makefile (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeLib/Makefile 2007-06-09 17:47:55 UTC (rev 934) @@ -0,0 +1,22 @@ +TARGET=arm-wince-mingw32ce + +CXX=$(TARGET)-g++ +AR=$(TARGET)-ar + +INCLUDES=-I../PipeDev/ + +ALLFLAGS=$(INCLUDES) $(CXXFLAGS) + +all: libPipeLib.a + +PipeLib.o: PipeLib.cpp + $(CXX) $< -c -o $@ $(ALLFLAGS) + +libPipeLib.a: PipeLib.o + rm -f $@ + $(AR) r $@ $< + +clean: + rm -f libPipeLib.a PipeLib.o + +.PHONE: all clean Property changes on: trunk/cegcc/tools/PipeLib/PipeLib/Makefile ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp 2007-06-09 17:47:55 UTC (rev 934) @@ -0,0 +1,218 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include <PipeDevice.h> + +#include <windows.h> +#include <devload.h> +#include <stdlib.h> + +#define KEY_NAME_BASE L"PipeDevice_" +#define NAME_BASE L"PD" /* Pipe Device */ +#define MAX_INSTANCES 99 + +#if 0 + +/* Doesn't work on CE < 5 ... */ +static int +FindFreeInstanceIndex (void) +{ + HANDLE h; + DEVMGR_DEVICE_INFORMATION di; + WCHAR wzName[6]; + for (int i=0; i < MAX_INSTANCES; i++) + { + wsprintf (wzName, L"%s%02d:", NAME_BASE, i); + di.dwSize = sizeof (di); + h = FindFirstDevice (DeviceSearchByLegacyName, wzName, &di); + if (h == INVALID_HANDLE_VALUE) + return i; + CloseHandle (h); + } + return -1; +} +#endif + +static void +PrepareRegistryForInstance (DWORD dwIndex, WCHAR** wzKey) +{ + DWORD dw; + HKEY hk; + WCHAR szKeyName[255]; + WCHAR wzPrefix[4]; //3 letter + zero character + DWORD dwDisp; + swprintf (wzPrefix, L"%s%d", NAME_BASE, dwIndex / 10); + + swprintf (szKeyName, L"Drivers\\%s%d", KEY_NAME_BASE, dwIndex); + *wzKey = wcsdup (szKeyName); + + if (ERROR_SUCCESS != RegCreateKeyEx (HKEY_LOCAL_MACHINE, + szKeyName, 0, NULL, 0, + KEY_WRITE, NULL, &hk, &dwDisp)) + { + wprintf (L"Failed to create registry key %s, error = %d\n", + szKeyName, (int) GetLastError ()); + return; + } + + RegSetValueEx (hk, L"dll", 0, REG_SZ, (BYTE *)DEVICE_DLL_NAME, + sizeof (DEVICE_DLL_NAME)); + RegSetValueEx (hk, L"prefix", 0, REG_SZ, (BYTE *)wzPrefix, + sizeof (wzPrefix)); + + dw = dwIndex % 10; + RegSetValueEx (hk, L"index", 0, REG_DWORD, (BYTE *)&dw, sizeof (dw)); + + dw = DEVFLAGS_LOADLIBRARY | DEVFLAGS_NAKEDENTRIES; + RegSetValueEx (hk, L"Flags", 0, REG_DWORD, (BYTE *)&dw, sizeof (dw)); + + RegCloseKey (hk); +} + +static BOOL +SetPipeName (HANDLE p, WCHAR* name) +{ + if (!DeviceIoControl (p, PIPE_IOCTL_SET_PIPE_NAME, + (LPVOID) name, (wcslen (name) + 1) * sizeof (WCHAR), + NULL, 0, NULL, NULL)) + return FALSE; + return TRUE; +} + +extern "C" BOOL +GetPipeName (HANDLE p, WCHAR* name) +{ + DWORD actual; + if (!DeviceIoControl (p, PIPE_IOCTL_GET_PIPE_NAME, + NULL, 0, + (LPVOID)name, MAX_PATH * sizeof (WCHAR), + &actual, NULL)) + return FALSE; + return TRUE; +} + +extern "C" BOOL +CreatePipe (PHANDLE hReadPipe, + PHANDLE hWritePipe, + LPSECURITY_ATTRIBUTES lpPipeAttributes, + DWORD nSize) +{ + int inst; + WCHAR* wsKey; + HANDLE h; + + *hReadPipe = NULL; + *hWritePipe = NULL; + + for (inst = 0 ; inst < MAX_INSTANCES; inst++) + { + PrepareRegistryForInstance (inst, &wsKey); + h = ActivateDevice (wsKey, 0); + RegDeleteKey (HKEY_LOCAL_MACHINE, wsKey); + free (wsKey); + + /* Although MSDN documentcs that error should + return INVALID_HANDLE_VALUE, I see it returning + NULL here. */ + if (h != INVALID_HANDLE_VALUE && h != NULL) + break; + } + + if (inst == MAX_INSTANCES) + return FALSE; + + /* name + num + ':' + '0' */ + wchar_t device_name[(sizeof (NAME_BASE) - 1) + 2 + 1 + 1]; + wsprintf (device_name, L"%s%02d:", NAME_BASE, inst); + + *hReadPipe = CreateFile (device_name, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + SetPipeName (*hReadPipe, device_name); + + *hWritePipe = CreateFile (device_name, + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + return TRUE; +} + +#if 0 + +struct PeekStruct +{ + DWORD Size; /* for future extension */ + PVOID lpBuffer, + DWORD nBufferSize, + + /* TODO: We need to use MapPtr for this to work */ + LPDWORD lpBytesRead, + LPDWORD lpTotalBytesAvail, + LPDWORD lpBytesLeftThisMessage + }; + +BOOL +PeekNamedPipe (HANDLE hNamedPipe, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesRead, + LPDWORD lpTotalBytesAvail, + LPDWORD lpBytesLeftThisMessage + ) +{ + DWORD avail; + DWORD actual; + + PeekStruct data; + data.Size = sizeof (PeekStruct); + data.lpBuffer = lpBuffer; + data.nBufferSize = nBufferSize; + data.lpBytesRead = lpBytesRead; + data.lpTotalBytesAvail = lpTotalBytesAvail; + data.lpBytesLeftThisMessage = lpBytesLeftThisMessage; + + if (!DeviceIoControl (hNamedPipe, PIPE_IOCTRL_PEEK_NAMED_PIPE, + NULL, 0, + (LPVOID)&data, sizeof (PeekStruct), &actual, NULL)) + return FALSE; + + /* We can detect here if we are talking to an older driver. */ + if (actual != data.Size) + return FALSE; + + return FALSE; +} + +#endif Property changes on: trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h 2007-06-09 17:47:55 UTC (rev 934) @@ -0,0 +1,43 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#ifndef __PIPE_LIB_H__ +#define __PIPE_LIB_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +BOOL CreatePipe (PHANDLE,PHANDLE,LPSECURITY_ATTRIBUTES,DWORD); +BOOL GetPipeName (HANDLE, WCHAR*); + +#ifdef __cplusplus +} +#endif + + +#endif Property changes on: trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/PipeLib/PipeTest/Makefile =================================================================== --- trunk/cegcc/tools/PipeLib/PipeTest/Makefile (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeTest/Makefile 2007-06-09 17:47:55 UTC (rev 934) @@ -0,0 +1,21 @@ +TARGET=arm-wince-mingw32ce + +CXX=$(TARGET)-g++ +AR=$(TARGET)-ar + +WARNFLAGS=-Wall -Wextra + +INCLUDES=-I../PipeLib +LIBS=-L../PipeLib -lPipeLib + +ALLFLAGS=$(INCLUDES) $(CXXFLAGS) $(WARNFLAGS) + +all: PipeTest.exe + +PipeTest.exe: PipeTest.cpp Makefile + $(CXX) $< -o $@ $(ALLFLAGS) $(LIBS) $(LDFLAGS) + +clean: + rm -f PipeTest.exe + +.PHONE: all clean Property changes on: trunk/cegcc/tools/PipeLib/PipeTest/Makefile ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/PipeLib/PipeTest/PipeTest.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeTest/PipeTest.cpp (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeTest/PipeTest.cpp 2007-06-09 17:47:55 UTC (rev 934) @@ -0,0 +1,172 @@ +/* Copyright (c) 2007, Pedro Alves + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +#include <windows.h> +#include <commctrl.h> + +#include <PipeLib.h> + +extern "C" BOOL GetStdioPathW(int, wchar_t*, DWORD*); +extern "C" BOOL SetStdioPathW(int, const wchar_t*); + +volatile BOOL stop = 0; + +static HANDLE readh[3]; +static HANDLE writeh[3]; + +static DWORD WINAPI +stdin_thread (void*) +{ + /* We don't need the reading side. */ + CloseHandle (readh[0]); + readh[0] = INVALID_HANDLE_VALUE; + + while (!stop) + { + DWORD read = 0; + char buf[1]; + + if (!ReadFile ((HANDLE) fileno (stdin), buf, sizeof (buf), &read, FALSE)) + { + OutputDebugStringW (L"stdin: broken pipe\n"); + break; + } + + if (read) + { + DWORD written = 0; + WriteFile (writeh[0], buf, read, &written, NULL); + } + } + + OutputDebugStringW(L"stdin thread gone\n"); + return 0; +} + +static DWORD WINAPI +stdout_thread (void*) +{ + /* We can't close the write side of the pipe until the + child opens its version. Since it will only be open on the + first stdout access, we have to wait until the read side returns + something - which means the child opened stdout. */ + + while (!stop) + { + DWORD read = 0; + char buf[1]; + if (!ReadFile (readh[1], buf, sizeof (buf), &read, FALSE)) + { + OutputDebugStringW (L"stout: broken pipe\n"); + break; + } + else if (writeh[1] != INVALID_HANDLE_VALUE) + { + /* We can now close our wr side. */ + CloseHandle (writeh[1]); + writeh[1] = INVALID_HANDLE_VALUE; + + } + if (read) + { + DWORD written = 0; + WriteFile ((HANDLE) fileno (stdout), buf, read, &written, NULL); + } + } + OutputDebugStringW(L"stdout thread gone\n"); + return 0; +} + + +void +create_inferior (const wchar_t *command, wchar_t** /* child_argv */) +{ + PROCESS_INFORMATION processInfo; + wchar_t prev_path[3][MAX_PATH]; + BOOL bRet; + + for (size_t i = 0; i < 3; i++) + { + wchar_t devname[MAX_PATH]; + if (!CreatePipe (&readh[i], &writeh[i], NULL, 0)) + return; + +#if 0 + CloseHandle (readh[i]); + CloseHandle (writeh[i]); + continue; +#endif + + GetPipeName (readh[i], devname); + DWORD dwLen = MAX_PATH; + GetStdioPathW (i, prev_path[i], &dwLen); + SetStdioPathW (i, devname); + } + + bRet = CreateProcess (command, L"", NULL, NULL, FALSE, 0, + NULL, NULL, NULL, &processInfo); + + if (!bRet) + return; + + for (size_t i = 0; i < 3; i++) + { + SetStdioPathW (i, prev_path[i]); + } + + HANDLE h[3]; + h[0] = CreateThread (NULL, 0, stdin_thread, NULL, 0, NULL); + h[1] = CreateThread (NULL, 0, stdout_thread, NULL, 0, NULL); + h[2] = processInfo.hProcess; + + switch (WaitForMultipleObjects (sizeof (h) / sizeof (h[0]), h, + FALSE, INFINITE)) + { + case WAIT_OBJECT_0: + stop = 1; + TerminateProcess (processInfo.hProcess, 0); + break; + case WAIT_OBJECT_0 + 1: + stop = 1; + TerminateProcess (processInfo.hProcess, 0); + break; + case WAIT_OBJECT_0 + 2: + stop = 1; + + // CloseHandle ((HANDLE) fileno (stdin)); + // TerminateThread (h[0], 0); + // TerminateThread (h[1], 0); + break; + default: + break; + } + + CloseHandle (h[0]); + CloseHandle (h[1]); + CloseHandle (processInfo.hProcess); + CloseHandle (processInfo.hThread); + for (int i = 0; i < 3; i++) + { + CloseHandle (writeh[i]); + } + + for (int i = 0; i < 3; i++) + { + CloseHandle (readh[i]); + } + return; +} + +int WINAPI +WinMain (HINSTANCE /*hInstance*/, + HINSTANCE /*hPrevInstance*/, + LPTSTR /*lpCmdLine*/, + int /*nCmdShow*/) +{ + wchar_t* child_argv[3] = {0}; + + create_inferior (L"TestClient.exe", child_argv); + return 0; +} Property changes on: trunk/cegcc/tools/PipeLib/PipeTest/PipeTest.cpp ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/PipeLib/TestClient/Makefile =================================================================== --- trunk/cegcc/tools/PipeLib/TestClient/Makefile (rev 0) +++ trunk/cegcc/tools/PipeLib/TestClient/Makefile 2007-06-09 17:47:55 UTC (rev 934) @@ -0,0 +1,21 @@ +TARGET=arm-wince-mingw32ce + +CXX=$(TARGET)-g++ +AR=$(TARGET)-ar + +WARNFLAGS=-Wall -Wextra + +INCLUDES= +LIBS= + +ALLFLAGS=$(INCLUDES) $(CXXFLAGS) $(WARNFLAGS) + +all: TestClient.exe + +TestClient.exe: TestClient.cpp Makefile + $(CXX) $< -o $@ $(ALLFLAGS) $(LIBS) $(LDFLAGS) + +clean: + rm -f TestClient.exe + +.PHONE: all clean Property changes on: trunk/cegcc/tools/PipeLib/TestClient/Makefile ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/PipeLib/TestClient/TestClient.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/TestClient/TestClient.cpp (rev 0) +++ trunk/cegcc/tools/PipeLib/TestClient/TestClient.cpp 2007-06-09 17:47:55 UTC (rev 934) @@ -0,0 +1,20 @@ +#include <windows.h> + +int WINAPI WinMain(HINSTANCE /*hInstance*/, + HINSTANCE /*hPrevInstance*/, + LPTSTR /*lpCmdLine*/, + int /*nCmdShow*/) +{ + int count = 0; + + for (int i = 0; i < 10; i++) + { + printf ("count = %d\n", count++); + Sleep (1000); + } + + // DWORD* zero = 0; + // return *zero; + + return 0; +} Property changes on: trunk/cegcc/tools/PipeLib/TestClient/TestClient.cpp ___________________________________________________________________ Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-10 20:45:46
|
Revision: 942 http://svn.sourceforge.net/cegcc/?rev=942&view=rev Author: pedroalves Date: 2007-06-10 13:44:04 -0700 (Sun, 10 Jun 2007) Log Message: ----------- Initial import of rshd. * COPYING, README, TODO, ChangeLog, Makefile, rshd.c, tester.c: New files. Added Paths: ----------- trunk/cegcc/tools/rshd/ trunk/cegcc/tools/rshd/COPYING trunk/cegcc/tools/rshd/ChangeLog trunk/cegcc/tools/rshd/Makefile trunk/cegcc/tools/rshd/README trunk/cegcc/tools/rshd/TODO trunk/cegcc/tools/rshd/rshd.c trunk/cegcc/tools/rshd/tester.c Added: trunk/cegcc/tools/rshd/COPYING =================================================================== --- trunk/cegcc/tools/rshd/COPYING (rev 0) +++ trunk/cegcc/tools/rshd/COPYING 2007-06-10 20:44:04 UTC (rev 942) @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. Added: trunk/cegcc/tools/rshd/ChangeLog =================================================================== --- trunk/cegcc/tools/rshd/ChangeLog (rev 0) +++ trunk/cegcc/tools/rshd/ChangeLog 2007-06-10 20:44:04 UTC (rev 942) @@ -0,0 +1,6 @@ +2007-06-10 Pedro Alves <ped...@po...> + + Initial import. + + * COPYING, README, TODO, ChangeLog, Makefile, rshd.c, tester.c: New + files. Property changes on: trunk/cegcc/tools/rshd/ChangeLog ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rshd/Makefile =================================================================== --- trunk/cegcc/tools/rshd/Makefile (rev 0) +++ trunk/cegcc/tools/rshd/Makefile 2007-06-10 20:44:04 UTC (rev 942) @@ -0,0 +1,76 @@ +TARGET=arm-wince-mingw32ce +LDFLAGS=-lws2 -lPipeLib +CFLAGS=-O0 -g3 +WARNFLAGS=-Wall -Wextra + +INCLUDES= + +ALLFLAGS=$(CFLAGS) $(INCLUDES) $(WARNFLAGS) + +CC=$(TARGET)-gcc + +BINS = rshd.exe tester.exe +STRIPPED_BINS = rshd-stripped.exe tester-stripped.exe + +LIBS = +TARGETS = $(BINS) $(LIBS) + +srcdir=. +distdir=rshd-0.1.0 +TAR = tar +TARFLAGS = z +TARFILEEXT = .tar.gz + +SRCDIST_FILES=\ + rshd.c tester.c Makefile README TODO COPYING ChangeLog + +BINDIST_FILES=\ + rshd.exe + +all: $(TARGETS) +bins: $(BINS) +libs: $(LIBS) + +rshd.exe: rshd.c Makefile + $(CC) -o $@ $< $(ALLFLAGS) $(LDFLAGS) + +rshd-stripped.exe: rshd.exe + $(TARGET)-strip $< -o $@ + +tester.exe: tester.c Makefile + $(CC) -o $@ $< $(ALLFLAGS) + +tester-stripped.exe: tester.exe + $(TARGET)-strip $< -o $@ + +download: rshd-stripped.exe tester-stripped.exe + pcp rshd-stripped.exe ":/rshd.exe" + pcp tester-stripped.exe ":/tester.exe" + +clean: + rm -f $(BINS) $(STRIPPED_BINS) $(LIBS) + +dist: srcdist bindist + +srcdist: all + rm -rf $(distdir) + mkdir $(distdir) + chmod 755 $(distdir) + for i in $(SRCDIST_FILES); do \ + cp -p $(srcdir)/$$i $(distdir)/$$i ; \ + done + rm -f $(distdir).tar.gz + $(TAR) $(TARFLAGS)cf $(distdir)-src$(TARFILEEXT) $(distdir) + +bindist: all + rm -rf $(distdir) + mkdir $(distdir) + chmod 755 $(distdir) + for i in $(BINDIST_FILES); do \ + cp -p $(srcdir)/$$i $(distdir)/$$i ; \ + done + rm -f $(distdir).tar.gz + $(TAR) $(TARFLAGS)cf $(distdir)-bin$(TARFILEEXT) $(distdir) + + +.PHONY: all install download clean dist bindist srcdist Property changes on: trunk/cegcc/tools/rshd/Makefile ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rshd/README =================================================================== --- trunk/cegcc/tools/rshd/README (rev 0) +++ trunk/cegcc/tools/rshd/README 2007-06-10 20:44:04 UTC (rev 942) @@ -0,0 +1,25 @@ + README for rshd for Windows CE + +This directory contains the rshd for Windows CE server. + +<TODO: how to build> + Depends on PipeLib. + PipeLib is found at the cegcc site. + +<TODO: how to run> + +<TODO: a note on (missing) security> + +Have fun! + +Pedro Alves + +-- + +See the file COPYING in the various directories, for a description of +the GNU General Public License terms under which you can copy the +files. + +REPORTING BUGS: +ce...@so... +pe...@po... Property changes on: trunk/cegcc/tools/rshd/README ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rshd/TODO =================================================================== --- trunk/cegcc/tools/rshd/TODO (rev 0) +++ trunk/cegcc/tools/rshd/TODO 2007-06-10 20:44:04 UTC (rev 942) @@ -0,0 +1,12 @@ +- Handle/test/pass child command line args. + +- What should be done with stdin echo? Should we do it, or not? Need + to test against a real rshd server see what happens there. + +- autotoolize. + +- Write a proper README.txt file. + +- Implement authentication using files or the registry. + +- Convert to service, and write a control panel applet ? Property changes on: trunk/cegcc/tools/rshd/TODO ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rshd/rshd.c =================================================================== --- trunk/cegcc/tools/rshd/rshd.c (rev 0) +++ trunk/cegcc/tools/rshd/rshd.c 2007-06-10 20:44:04 UTC (rev 942) @@ -0,0 +1,899 @@ +/* rshd for Windows CE. + + Copyright (C) 2007, Pedro M. P. Alves + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + + Originally based on rlogind from GNUWINCE by Voxware Inc., + rewritten as native Windows CE application using PipeLib + and mingw32ce. */ + +#include <sys/types.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <stdarg.h> +#include <malloc.h> + +#include <windows.h> +#include <winsock2.h> +#include <pkfuncs.h> + +#include <PipeLib.h> + +#ifndef COUNTOF +#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0])) +#endif + +static BOOL debug = FALSE; + + + +static void +logprintf (const char *fmt, ...) +{ + if (0) + { + FILE *logfile = fopen("/rshd.log", "a+"); + + if (logfile) + { + va_list ap; + va_start (ap, fmt); + vfprintf (logfile, fmt, ap); + va_end (ap); + fclose (logfile); + } + } + else if (debug) + { + va_list ap; + va_start (ap, fmt); + vfprintf (stderr, fmt, ap); + fflush (stderr); + va_end (ap); + } +} + +/* Map the Windows error number in ERROR to a locale-dependent error + message string and return a pointer to it. Typically, the values + for ERROR come from GetLastError. + + The string pointed to shall not be modified by the application, + but may be overwritten by a subsequent call to strwinerror + + The strwinerror function does not change the current setting + of GetLastError. */ + +char * +strwinerror (DWORD error) +{ + static char buf[1024]; + TCHAR *msgbuf; + DWORD lasterr = GetLastError (); + DWORD chars = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) + { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' + && msgbuf[chars - 1] == '\n') + { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > ((COUNTOF (buf)) - 1)) + { + chars = COUNTOF (buf) - 1; + msgbuf [chars] = 0; + } + + wcstombs (buf, msgbuf, chars + 1); + LocalFree (msgbuf); + } + else + sprintf (buf, "unknown win32 error (%ld)", error); + + SetLastError (lasterr); + return buf; +} + +void +perror (const char *s) +{ + if (s && *s) + fprintf (stderr, "%s: %s\n", s, strwinerror (GetLastError ())); + else + fprintf (stderr, "%s\n", strwinerror (GetLastError ())); +} + + + +struct client_data_t +{ + int clientid; + /* stdin/stdout */ + int sockfd; + + /* stderr */ + int stderrsockfd; + + /* remote */ + struct sockaddr_in sin; + + /* pipe handles for stdin/stdout/stderr. */ + HANDLE readh[3]; + HANDLE writeh[3]; + + /* stop request */ + volatile BOOL stop; + + long refcount; +}; + +static void +addref_data (struct client_data_t * data) +{ + InterlockedIncrement (&data->refcount); +} + +static void +release_data (struct client_data_t * data) +{ + if (InterlockedDecrement (&data->refcount) == 0) + { + logprintf ("Connection from %s:%d terminated\n", + inet_ntoa (data->sin.sin_addr), + ntohs (data->sin.sin_port)); + free (data); + } +} + +static void +init_client_data (struct client_data_t *data) +{ + static int clientid = 0; + int i; + + memset (&data->sin, 0, sizeof (data->sin)); + + data->clientid = ++clientid; + data->sockfd = data->stderrsockfd = -1; + + for (i = 0; i < 3; i++) + { + data->readh[0] = INVALID_HANDLE_VALUE; + data->writeh[0] = INVALID_HANDLE_VALUE; + } + + data->stop = FALSE; +} + +/* check if hostname is in users .rhost file */ +static int +rsh_userok (const char *hostname, const char *user) +{ +#if 0 + struct passwd *pw; + char s[256] = ""; + FILE *f; + if ((pw = getpwnam (user)) == NULL) + return 0; + strcpy (s, pw->pw_dir); + strcat (s, "/.rhosts"); + if ((f = fopen (s, "r")) == NULL) + return 0; + while (fgets (s, sizeof (s), f)) + { + char *p; + p = strchr (s, '\n'); + if (p) + *p = 0; + p = strchr (s, '\r'); + if (p) + *p = 0; + if (strcmp (hostname, s) == 0) + { + fclose (f); + return 1; + } + } + fclose (f); + return 0; +#endif + (void)hostname; + (void)user; + return 1; +} + +int +rexec_userok (const char *user, const char *pass) +{ +#if 0 + struct passwd *pw; + char s[256] = ""; + if ((pw = getpwnam(user)) == NULL) + return 0; + + if (strncmp(pw->pw_passwd, pass, 13) != 0) + return 0; +#endif + (void)user; + (void)pass; + return 1; +} + +static DWORD WINAPI +stdin_thread (void *arg) +{ + struct client_data_t *data = arg; + const char *thread_name = "stdin_thread"; + + addref_data (data); + + /* We don't need the reading side. */ + CloseHandle (data->readh[0]); + data->readh[0] = INVALID_HANDLE_VALUE; + + while (!data->stop) + { + int read = 0; + char buf[1]; + + read = recv (data->sockfd, buf, sizeof(buf), 0); + if (read < 0) + { + DWORD err = WSAGetLastError (); + switch (err) + { + case WSAECONNRESET: + case WSAEINTR: + if (!data->stop) + /* only be verbose if we were not expecting it. */ + logprintf ("%s: connection reset.\n", thread_name); + break; + default: + logprintf ("%s: recv ERROR, winerr %d\n", thread_name, err); + break; + } + break; + } + else if (read == 0) + { + logprintf ("%s: connection closed\n", thread_name); + break; + } + + if (read) + { + int written; + DWORD dwwritten; + +#if 1 + /* echo data back ... */ + written = send (data->sockfd, buf, read, 0); + if (written < 0) + logprintf ("%s: write ERROR, winerr %d\n", + thread_name, + GetLastError ()); + else if (written < read) + logprintf ("%s: ERROR only wrote %d of %d bytes\n", + thread_name, written, read); +#endif + + /* ... and stuff it into the child's stdin. */ + if (!WriteFile (data->writeh[0], buf, read, &dwwritten, NULL)) + { + logprintf ("%s: broken pipe (2)\n", thread_name); + break; + } + } + } + + release_data (data); + logprintf ("%s gone\n", thread_name); + return 0; +} + +static DWORD WINAPI +stdout_thread (void *arg) +{ + struct client_data_t *data = arg; + const char *thread_name = "stdout_thread"; + + addref_data (data); + + while (!data->stop) + { + DWORD read = 0; + char buf[256]; + if (!ReadFile (data->readh[1], buf, sizeof (buf), &read, FALSE)) + { + logprintf ("%s: broken pipe\n", thread_name); + break; + } + else if (data->writeh[1] != INVALID_HANDLE_VALUE) + { + /* We can't close the write side of the pipe until the + child opens its version. Since it will only be open on the + first stdout access, we have to wait until the read side returns + something - which means the child opened stdout. */ + CloseHandle (data->writeh[1]); + data->writeh[1] = INVALID_HANDLE_VALUE; + } + if (read) + { + int written = send (data->sockfd, buf, read, 0); + if (written < 0) + logprintf ("%s: write ERROR, winerr %d\n", + thread_name, + GetLastError ()); + else if ((DWORD) written < read) + logprintf ("%s: ERROR only wrote %d of %d bytes\n", + thread_name, written, read); + } + } + + release_data (data); + logprintf ("%s gone\n", thread_name); + return 0; +} + +static DWORD WINAPI +stderr_thread (void *arg) +{ + struct client_data_t *data = arg; + const char *thread_name = "stderr_thread"; + int sockfd; + + addref_data (data); + + sockfd = data->stderrsockfd; + if (sockfd == -1) + /* If we don't have a separate stderr channel, send the data + as if it came through stdout. */ + sockfd = data->sockfd; + + while (!data->stop) + { + DWORD read = 0; + char buf[256]; + + if (!ReadFile (data->readh[2], buf, sizeof (buf), &read, FALSE)) + { + logprintf ("%s: broken pipe\n", thread_name); + break; + } + else if (data->writeh[2] != INVALID_HANDLE_VALUE) + { + /* We can't close the write side of the pipe until the + child opens its version. Since it will only be open on the + first stderr access, we have to wait until the read side returns + something - which means the child opened stderr. */ + CloseHandle (data->writeh[2]); + data->writeh[2] = INVALID_HANDLE_VALUE; + } + if (read) + { + int written = send (sockfd, buf, read, 0); + if (written < 0) + logprintf ("%s: write ERROR, winerr %d\n", + thread_name, + GetLastError ()); + else if ((DWORD) written < read) + logprintf ("%s: ERROR only wrote %d of %d bytes\n", + thread_name, written, read); + } + } + + release_data (data); + logprintf ("%s gone\n", thread_name); + return 0; +} + +static void +to_back_slashes (char *path) +{ + for (; *path; ++path) + if ('/' == *path) + *path = '\\'; +} + +/* Start a new process. + Returns the new process' handle on success, NULL on failure. */ +static HANDLE +create_child (char *program, HANDLE *readh, HANDLE *writeh) +{ + BOOL ret; + char *args; + int argslen; + PROCESS_INFORMATION pi; + wchar_t *wargs, *wprogram; + wchar_t prev_path[3][MAX_PATH]; + size_t i; + + if (program == NULL || program[0] == '\0') + { + fprintf (stderr, + "No executable specified, specify executable to control.\n"); + return NULL; + } + + argslen = 0; + args = ""; + + to_back_slashes (program); + wargs = alloca ((argslen + 1) * sizeof (wchar_t)); + mbstowcs (wargs, args, argslen); + wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t)); + mbstowcs (wprogram, program, strlen (program) + 1); + + /* Do the PipeLib/WinCE dup dance. */ + + for (i = 0; i < 3; i++) + { + wchar_t devname[MAX_PATH]; + if (!CreatePipe (&readh[i], &writeh[i], NULL, 0)) + return NULL; + + GetPipeName (readh[i], devname); + DWORD dwLen = MAX_PATH; + GetStdioPathW (i, prev_path[i], &dwLen); + SetStdioPathW (i, devname); + } + + ret = CreateProcessW (wprogram, /* image name */ + wargs, /* command line */ + NULL, /* security, not supported */ + NULL, /* thread, not supported */ + FALSE, /* inherit handles, not supported */ + 0, /* start flags */ + NULL, /* environment, not supported */ + NULL, /* current directory, not supported */ + NULL, /* start info, not supported */ + &pi); /* proc info */ + + for (i = 0; i < 3; i++) + SetStdioPathW (i, prev_path[i]); + + if (!ret) + { + DWORD err = GetLastError (); + fprintf (stderr, "Error creating process \"%s%s\", (error %d): %s\n", + program, args, (int) err, strwinerror (err)); + + for (i = 0; i < 3; i++) + { + CloseHandle (readh[i]); + CloseHandle (writeh[i]); + } + return NULL; + } + else + logprintf ("Process created: %s\n", program); + + CloseHandle (pi.hThread); + pi.hThread = NULL; + + return pi.hProcess; +} + +static int +rresvport (int *alport) +{ + struct sockaddr_in sin; + int s; + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + s = socket (AF_INET, SOCK_STREAM, 0); + if (s == -1) + return -1; + + for (;;) + { + sin.sin_port = htons ((USHORT) *alport); + if (bind (s, (struct sockaddr *) &sin, sizeof(sin)) == 0) + return s; + + if (WSAGetLastError () != WSAEADDRINUSE) + { + closesocket (s); + return -1; + } + (*alport)--; + if (*alport == IPPORT_RESERVED / 2) + { + closesocket (s); + return -1; + } + } +} + +int +connect_stderr (int in, unsigned short stderr_port) +{ + int s; + int lport = IPPORT_RESERVED - 1; + struct sockaddr_in sin; + int len = sizeof (sin); + + logprintf ("Connecting stderr to remote port %d\n", stderr_port); + if (getpeername (in, (struct sockaddr *) &sin, &len) == -1) + { + perror ("getpeername"); + return -1; + } + + for (;;) + { + if ((s = rresvport (&lport)) == -1) + { + perror ("rresvport"); + return -1; + } + + sin.sin_port = htons (stderr_port); + if (connect (s, (struct sockaddr *) &sin, sizeof(sin)) == -1) + { + closesocket (s); + if (WSAGetLastError () == WSAEADDRINUSE) + { + lport--; + continue; + } + + logprintf ("connect: %s\n", strwinerror (WSAGetLastError ()));; + closesocket (s); + return -1; + } + + logprintf ("Using resvport %d\n", lport); + break; + } + + return s; +} + +static WINAPI DWORD +handle_connection (void *arg) +{ + int s2 = (int) arg; /* sizeof (void*) == sizeof (int) */ + int stderrsockfd = -1; + unsigned short stderr_port = 0; + int cc; + char c, *p; + char stderrport[100] = ""; + char locuser[0x101] = ""; + char remuser[0x101] = ""; + char command[8193]; + int len = sizeof (struct sockaddr_in); + struct hostent *hp; + const char *peername; + struct linger linger; + + struct client_data_t* client_data; + + HANDLE waith[4]; + HANDLE hndproc; + DWORD tid[3]; + size_t i; + int enabled = 1; + /* int disabled = 0; */ + + logprintf ("handle_conn: STARTED\n"); + + client_data = malloc (sizeof (*client_data)); + init_client_data (client_data); + addref_data (client_data); + + /* Allow rapid reuse of this port. */ + if (setsockopt (s2, SOL_SOCKET, SO_REUSEADDR, + (char *) &enabled, sizeof (enabled)) < 0) + { + perror ("setsockopt (SO_KEEPALIVE)"); + goto shutdown; + } + + /* Enable TCP keep alive process. */ + if (setsockopt (s2, SOL_SOCKET, SO_KEEPALIVE, + (char *) &enabled, sizeof (enabled)) < 0) + { + perror ("setsockopt (SO_KEEPALIVE)"); + goto shutdown; + } + + linger.l_onoff = 1; + linger.l_linger = 60; +#if 0 + if (setsockopt (s2, SOL_SOCKET, SO_LINGER, (char *)&linger, + sizeof (linger)) < 0) + { + perror ("setsockopt (SO_LINGER)"); + goto shutdown; + } +#endif + + /* Tell TCP not to delay small packets. This greatly speeds up + interactive response. */ + if (setsockopt (s2, IPPROTO_TCP, TCP_NODELAY, + (char *) &enabled, sizeof (enabled)) < 0) + { + perror ("setsockopt (TCP_NODELAY)"); + goto shutdown; + } + + if (getpeername (s2, (struct sockaddr *) &client_data->sin, &len) == -1) + { + perror ("getpeername"); + goto shutdown; + } + + /* Verify that the client's address is an Internet adress. */ + if (client_data->sin.sin_family != AF_INET) + { + fprintf (stderr, "malformed \"from\" address (af %d)\n", + client_data->sin.sin_family); + goto shutdown; + } + + hp = gethostbyaddr ((char *) &client_data->sin.sin_addr, + sizeof(client_data->sin.sin_addr), PF_INET); + + peername = (hp != NULL) + ? hp->h_name + : "unknown"; + + logprintf ("Connection from (%s) %s:%d...\n", + peername, + inet_ntoa (client_data->sin.sin_addr), + ntohs (client_data->sin.sin_port)); + + /* get stderr port. */ + p = stderrport; + while ((cc = recv (s2, &c, 1, 0)) > 0 && c != 0) + *p++ = c; + *p = 0; + + + if ((stderr_port = atoi (stderrport)) > 0) + { + stderrsockfd = connect_stderr (s2, stderr_port); + if (stderrsockfd == -1) + { + logprintf ("cannot connect stderr\n"); + goto shutdown; + } + } + + if (cc == -1) + { + logprintf ("error reading stderr port: %s\n", + strwinerror (GetLastError ())); + goto shutdown; + } + + p = locuser; + while ((cc = recv (s2, &c, 1, 0)) > 0 && c != 0) + *p++ = c; + *p = 0; + if (cc == -1) + { + logprintf ("error reading user name: %s\n", + strwinerror (GetLastError ())); + goto shutdown; + } + + p = remuser; + while ((cc = recv (s2, &c, 1, 0)) > 0 && c != 0) + *p++ = c; + *p = 0; + + if (cc == -1) + { + logprintf ("error reading rem user/password: %s\n", + strwinerror (GetLastError ())); + goto shutdown; + } + + p = command; + while ((cc = recv (s2, &c, 1, 0)) > 0 && c != 0) + *p++ = c; + *p = 0; + if (cc == -1) + { + logprintf ("error reading command: %s\n", strwinerror (GetLastError ())); + goto shutdown; + } + logprintf ("Local user: %s\nRemote user: %s\nCommand: %s\n", + locuser, remuser, command); +#if 0 + if (!hp || !rsh_userok (hp->h_name, remuser)) + { /* check .rhosts */ + char *s = "Permission denied\n"; + send (s2, s, strlen (s) + 1, 0); + goto shutdown; + } +#endif + + /* send OK */ + send (s2, "", 1, 0); + + logprintf ("handle_connection: starting command... \n"); + hndproc = create_child (command, client_data->readh, client_data->writeh); + if (!hndproc) + { + logprintf ("handle_connection: ERROR can't create child process, " + "winerr %d\n", GetLastError ()); + goto shutdown; + } + + client_data->sockfd = s2; + client_data->stderrsockfd = stderrsockfd; + + waith[0] = CreateThread (NULL, 0, stdin_thread, client_data, 0, &tid[0]); + waith[1] = CreateThread (NULL, 0, stdout_thread, client_data, 0, &tid[1]); + waith[2] = CreateThread (NULL, 0, stderr_thread, client_data, 0, &tid[2]); + waith[3] = hndproc; + + switch (WaitForMultipleObjects (COUNTOF (waith), waith, FALSE, INFINITE)) + { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + case WAIT_OBJECT_0 + 2: + TerminateProcess (hndproc, 0); + break; + case WAIT_OBJECT_0 + 3: + break; + default: + logprintf ("WaitForMultipleObjects' default reached\n"); + break; + } + + client_data->stop = TRUE; + + for (i = 0; i < 4; i++) + CloseHandle (waith[i]); + + for (i = 0; i < 3; i++) + { + CloseHandle (client_data->writeh[i]); + CloseHandle (client_data->readh[i]); + } + + shutdown: + logprintf ("Shutting down connection from %s:%d...\n", + inet_ntoa (client_data->sin.sin_addr), + ntohs (client_data->sin.sin_port)); + + /* close sockets */ + shutdown (s2, 2); + closesocket (s2); + if (stderrsockfd != -1) + { + shutdown (stderrsockfd, 2); + closesocket (stderrsockfd); + } + + release_data (client_data); + + /* maybe we should wait for all the still alive threads again? */ + + return 0; +} + +static void +accept_connections (void) +{ + int s; + struct sockaddr_in sin; + USHORT port = 0; + struct hostent *phe; + int i; + char ac[80]; + + port = 514; + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + + if ((s = socket (AF_INET, SOCK_STREAM, 0)) == -1) + { + perror ("socket"); + exit (1); + } + + sin.sin_port = htons(port); + if (bind (s, (struct sockaddr *) &sin, sizeof (sin)) != 0) + { + perror ("bind"); + closesocket (s); + exit (1); + } + + /* 10 is the maximum backlog allowed */ + if (listen (s, 10) != 0) + { + perror ("listen"); + closesocket (s); + exit (1); + } + + if (gethostname (ac, sizeof(ac)) == SOCKET_ERROR) + { + fprintf (stderr, "Error %d when getting local host name.\n", + WSAGetLastError()); + exit (1); + } + printf ("Host name is %s.\n", ac); + + phe = gethostbyname (ac); + if (phe == NULL) + { + fprintf (stderr, "Yow! Bad host lookup.\n"); + exit (1); + } + + for (i = 0; phe->h_addr_list[i] != 0; ++i) + { + struct in_addr addr; + memcpy (&addr, phe->h_addr_list[i], sizeof (struct in_addr)); + printf ("Address %d: %s\n", i, inet_ntoa (addr)); + } + + logprintf ("rshd ready\n\n"); + for (;;) + { + HANDLE connThread; + int s2; + + logprintf ("Listening on port %d...\n", port); + if ((s2 = accept (s, NULL, NULL)) == -1) + { + perror ("accept"); + closesocket (s); + exit (1); + } + + logprintf ("handle_conn: accepted\n"); + connThread = CreateThread (NULL, 0, + handle_connection, + (LPVOID)s2, 0, NULL); + CloseHandle (connThread); + logprintf ("CreateThread (connThread) returns\n"); + } +} + +int +main (int argc, char **argv) +{ + WSADATA wsad; + WSAStartup (MAKEWORD (2, 0), &wsad); + + if (argc > 1 && strcmp(argv[1], "-d") == 0) + debug = 1; + + accept_connections (); + return 0; +} Property changes on: trunk/cegcc/tools/rshd/rshd.c ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rshd/tester.c =================================================================== --- trunk/cegcc/tools/rshd/tester.c (rev 0) +++ trunk/cegcc/tools/rshd/tester.c 2007-06-10 20:44:04 UTC (rev 942) @@ -0,0 +1,25 @@ +#include <stdio.h> +#include <windows.h> + +int main () +{ + int counter = 0; + int i; + for (i = 0; i < 3; i++) + { + printf ("counter = %d\n", counter++); + Sleep (300); + } + + for (i = 0; i < 3; i++) + { + int num; + printf ("write a num:"); + scanf ("%d", &num); + printf ("written = %d\n", num); + } + + printf ("exiting\n"); + Sleep (3000); + return 0; +} Property changes on: trunk/cegcc/tools/rshd/tester.c ___________________________________________________________________ Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-25 01:06:17
|
Revision: 1006 http://svn.sourceforge.net/cegcc/?rev=1006&view=rev Author: pedroalves Date: 2007-06-24 18:06:15 -0700 (Sun, 24 Jun 2007) Log Message: ----------- Initial import. * LICENSE, README, TODO, ChangeLog, Makefile, errno.c errno.tab, errno_h.awk, errno_str.awk, errno_tab.awk: New files. Added Paths: ----------- trunk/cegcc/tools/errno/ trunk/cegcc/tools/errno/ChangeLog trunk/cegcc/tools/errno/LICENSE trunk/cegcc/tools/errno/Makefile trunk/cegcc/tools/errno/README trunk/cegcc/tools/errno/TODO trunk/cegcc/tools/errno/errno.c trunk/cegcc/tools/errno/errno.tab trunk/cegcc/tools/errno/errno_h.awk trunk/cegcc/tools/errno/errno_str.awk trunk/cegcc/tools/errno/errno_tab.awk Added: trunk/cegcc/tools/errno/ChangeLog =================================================================== --- trunk/cegcc/tools/errno/ChangeLog (rev 0) +++ trunk/cegcc/tools/errno/ChangeLog 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,14 @@ +2007-06-25 Pedro Alves <ped...@po...> + + Initial import. + + * LICENSE, README, TODO, ChangeLog, Makefile, errno.c errno.tab, + errno_h.awk, errno_str.awk, errno_tab.awk: New files. + + +Local Variables: +mode: change-log +left-margin: 8 +fill-column: 74 +version-control: never +End: Property changes on: trunk/cegcc/tools/errno/ChangeLog ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/errno/LICENSE =================================================================== --- trunk/cegcc/tools/errno/LICENSE (rev 0) +++ trunk/cegcc/tools/errno/LICENSE 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,25 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ Added: trunk/cegcc/tools/errno/Makefile =================================================================== --- trunk/cegcc/tools/errno/Makefile (rev 0) +++ trunk/cegcc/tools/errno/Makefile 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,38 @@ +TARGET=arm-wince-mingw32ce + +CC=$(TARGET)-gcc +AR=$(TARGET)-ar + +INCLUDES=-I. +ALLFLAGS=$(CFLAGS) $(INCLUDES) + +GENFILES=errno.h errno_tab.c errno_str.c +OBJECTS=errno.o + +all: liberrno.a + +errno_tab.c: errno.tab errno_tab.awk Makefile + awk '{ print $$2 " " $$1 }' < errno.tab | sort | awk -f errno_tab.awk > $@ + +errno_str.c: errno.tab errno_str.awk Makefile + awk -f errno_str.awk < errno.tab > $@ + +errno.h: errno.tab errno_h.awk Makefile + awk -f errno_h.awk < errno.tab > $@ + +errno.o: errno.c errno_tab.c errno_str.c errno.h Makefile + $(CC) -c -o $@ $< $(ALLFLAGS) + +liberrno.a: errno.o Makefile + rm -f $@ + $(AR) r $@ $< + +clean: + rm -f liberrno.a $(OBJECTS) + +distclean: clean + rm -f $(GENFILES) + +regen: distclean $(GENFILES) + +.PHONY: all clean regen Property changes on: trunk/cegcc/tools/errno/Makefile ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/errno/README =================================================================== --- trunk/cegcc/tools/errno/README (rev 0) +++ trunk/cegcc/tools/errno/README 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,28 @@ +This is an errno <-> {Get|Set}LastError mapper. + +<describe here the technique used> + +Do *not* install errno.h into +/opt/mingw32ce/arm-wince-mingw32ce/include. + +You have been warned. + +This is only used as a porting aid. Ideally you use this as an +interim measure until you finish the port. If you chose to keep using +it, and you are writing a lib to be reused by others, be sure to *NOT* +export any header that includes errno.h. Do *NOT* expect your users +to have errno.h. If needed, copy errno.h and errno.c into your +project, but again, do *NOT* force it into the users. + +Have fun! + +Pedro Alves + +-- + +See the file LICENSE in the various directories, for a description of +the license the software is license in. + +REPORTING BUGS: +ce...@so... +pe...@po... Property changes on: trunk/cegcc/tools/errno/README ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/errno/TODO =================================================================== --- trunk/cegcc/tools/errno/TODO (rev 0) +++ trunk/cegcc/tools/errno/TODO 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1 @@ + Property changes on: trunk/cegcc/tools/errno/TODO ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/errno/errno.c =================================================================== --- trunk/cegcc/tools/errno/errno.c (rev 0) +++ trunk/cegcc/tools/errno/errno.c 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,112 @@ +/* Pedro Alves */ + +#include "errno.h" +#include <windows.h> + +/* There are more WinErr codes than errno codes. + To prevent having to do stuff like: + +- if (errno == ENOENT) ++ if (errno == ERROR_PATH_NOT_FOUND ++ || errno == ERROR_FILE_NOT_FOUND) + + ... we colapse the multiple WinErr mappings into one. */ + +int +__liberrno_errno (void) +{ + DWORD winerr = GetLastError (); + switch (winerr) + { +#include "errno_tab.c" + default: + return (int) winerr; + } +} + +#ifndef COUNTOF +#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0])) +#endif + +/* Map the Windows error number in ERROR to a locale-dependent error + message string and return a pointer to it. Typically, the values + for ERROR come from GetLastError. + + The string pointed to shall not be modified by the application, + but may be overwritten by a subsequent call to strwinerror + + The strwinerror function does not change the current setting + of GetLastError. */ + +static char * +strwinerror (char* buf, DWORD error) +{ + wchar_t *msgbuf; + DWORD lasterr = GetLastError (); + DWORD chars = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) + { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' + && msgbuf[chars - 1] == '\n') + { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > ((COUNTOF (buf)) - 1)) + { + chars = COUNTOF (buf) - 1; + msgbuf [chars] = 0; + } + + wcstombs (buf, msgbuf, chars + 1); + LocalFree (msgbuf); + } + else + sprintf (buf, "unknown win32 error (%ld)", error); + + SetLastError (lasterr); + return buf; +} + +__inline__ static const char* +get_errstr (DWORD winerr) +{ + switch (winerr) + { +#include "errno_str.c" + } + return NULL; +} + +char * +strerror (int error) +{ + static char buf[1024]; + DWORD winerr = (DWORD) error; + const char *str = get_errstr (winerr); + + if (str != NULL) + strcpy (buf, str); + else + strwinerror (buf, winerr); + return buf; +} + +void +perror (const char *s) +{ + if (s && *s) + fprintf (stderr, "%s: %s\n", s, strerror (errno)); + else + fprintf (stderr, "%s\n", strerror (errno)); +} Property changes on: trunk/cegcc/tools/errno/errno.c ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/errno/errno.tab =================================================================== --- trunk/cegcc/tools/errno/errno.tab (rev 0) +++ trunk/cegcc/tools/errno/errno.tab 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,165 @@ +# libceerrno v1.0 +# +# errno to Windows error mapping. + +EACCES ERROR_ACCESS_DENIED "Permission denied" +EACCES ERROR_LOCK_VIOLATION +EACCES ERROR_SHARING_VIOLATION + +EAGAIN ERROR_MORE_DATA "Resource temporarily unavailable" +EAGAIN ERROR_ACTIVE_CONNECTIONS +EAGAIN ERROR_DEVICE_IN_USE +EAGAIN ERROR_MAX_THRDS_REACHED +EAGAIN ERROR_NO_PROC_SLOTS +EAGAIN ERROR_OPEN_FILES + +EBADF ERROR_INVALID_HANDLE "Bad file descriptor" + +EBADRQC ERROR_INVALID_FUNCTION "Invalid request code" + +EBUSY ERROR_BUSY "Device or resource busy" +EBUSY ERROR_CHILD_NOT_COMPLETE +EBUSY ERROR_PIPE_BUSY +EBUSY ERROR_PIPE_CONNECTED +EBUSY ERROR_SIGNAL_PENDING + +ECHILD ERROR_WAIT_NO_CHILDREN "No child processes" + +ECOMM ERROR_PIPE_LISTENING "Communication error on send" +ECOMM ERROR_PIPE_NOT_CONNECTED + +EDEADLOCK ERROR_POSSIBLE_DEADLOCK "File locking deadlock error" + +EEXIST ERROR_FILE_EXISTS "File exists" +EEXIST ERROR_ALREADY_EXISTS + +EFAULT ERROR_PROCESS_ABORTED "Bad address" +EFAULT ERROR_NOACCESS + +EINTR ERROR_INVALID_AT_INTERRUPT_TIME "Interrupted system call" + +EINVAL ERROR_INVALID_PARAMETER "Invalid argument" +EINVAL ERROR_BAD_PIPE +EINVAL ERROR_BAD_USERNAME +EINVAL ERROR_FILENAME_EXCED_RANGE +EINVAL ERROR_INVALID_DATA +EINVAL ERROR_INVALID_SIGNAL_NUMBER +EINVAL ERROR_META_EXPANSION_TOO_LONG +EINVAL ERROR_NEGATIVE_SEEK +EINVAL ERROR_NO_TOKEN +EINVAL ERROR_THREAD_1_INACTIVE + +EIO ERROR_IO_DEVICE "Input/Output error" +EIO ERROR_CRC +EIO ERROR_NO_SIGNAL_SENT +EIO ERROR_OPEN_FAILED +EIO ERROR_SIGNAL_REFUSED + +EMFILE ERROR_TOO_MANY_OPEN_FILES "Too many open files" +ENFILE ERROR_NO_MORE_SEARCH_HANDLES + +ENMFILE ERROR_NO_MORE_FILES "No more files" + +ENODATA ERROR_HANDLE_EOF "No data available" + +ENODEV ERROR_BAD_DEVICE "No such device" +ENODEV ERROR_BAD_UNIT +ENODEV ERROR_INVALID_DRIVE + +ENOENT ERROR_FILE_NOT_FOUND "No such file or directory" +ENOENT ERROR_BAD_PATHNAME +ENOENT ERROR_INVALID_NAME +ENOENT ERROR_PATH_NOT_FOUND + +ENOERR NO_ERROR "No error" + +ENOLCK ERROR_SHARING_BUFFER_EXCEEDED "No locks available" + +ENOLINK ERROR_NOT_CONNECTED "Link has been severed" + +ENOMEDIUM ERROR_NOT_READY "No medium found" + +ENOMEM ERROR_NOT_ENOUGH_MEMORY "Cannot allocate memory" +ENOMEM ERROR_OUTOFMEMORY + +ENONET ERROR_REM_NOT_LIST "Machine is not on the network" + +ENOSHARE ERROR_BAD_NETPATH "No such host or network path" +ENOSHARE ERROR_BAD_NET_NAME + +ENOSPC ERROR_DISK_FULL "No space left on device" +ENOSPC ERROR_END_OF_MEDIA +ENOSPC ERROR_EOM_OVERFLOW +ENOSPC ERROR_HANDLE_DISK_FULL +ENOSPC ERROR_NO_DATA_DETECTED + +ENOSYS ERROR_CALL_NOT_IMPLEMENTED "Function not implemented" +ENOSYS ERROR_NOT_SUPPORTED + +ENOTDIR ERROR_DIRECTORY "Not a directory" + +ENOTEMPTY ERROR_DIR_NOT_EMPTY "Directory not empty" +ENOTEMPTY WSAENOTEMPTY + +ENOTUNIQ ERROR_DUP_NAME "Name not unique on network" + +ENXIO ERROR_FILE_INVALID "No such device or address" + +EOVERFLOW ERROR_ARITHMETIC_OVERFLOW "Value too large for defined data type" + +EPERM ERROR_CANNOT_MAKE "Operation not permitted" +EPERM ERROR_NOT_OWNER + +EPIPE ERROR_BROKEN_PIPE "Broken pipe" +EPIPE ERROR_NO_DATA + +# also defined as EOVERFLOW above +ERANGE ERROR_ARITHMETIC_OVERFLOW + +EROFS ERROR_WRITE_PROTECT "Read-only file system" + +ESPIPE ERROR_BEGINNING_OF_MEDIA "Illegal seek" +ESPIPE ERROR_SETMARK_DETECTED + +EXDEV ERROR_NOT_SAME_DEVICE "Invalid cross-device link" + +# Winsock codes + +EWOULDBLOCK +EINPROGRESS WSAEINPROGRESS +EALREADY WSAEALREADY +ENOTSOCK WSAENOTSOCK +EDESTADDRREQ WSAEDESTADDRREQ +EMSGSIZE WSAEMSGSIZE +EPROTOTYPE WSAEPROTOTYPE +ENOPROTOOPT WSAENOPROTOOPT +EPROTONOSUPPORT WSAEPROTONOSUPPORT +ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT +EOPNOTSUPP WSAEOPNOTSUPP +EPFNOSUPPORT WSAEPFNOSUPPORT +EAFNOSUPPORT WSAEAFNOSUPPORT +EADDRINUSE WSAEADDRINUSE +EADDRNOTAVAIL WSAEADDRNOTAVAIL +ENETDOWN WSAENETDOWN +ENETUNREACH WSAENETUNREACH +ENETRESET WSAENETRESET +ECONNABORTED WSAECONNABORTED +ECONNRESET WSAECONNRESET +ENOBUFS WSAENOBUFS +EISCONN WSAEISCONN +ENOTCONN WSAENOTCONN +ESHUTDOWN WSAESHUTDOWN +ETOOMANYREFS WSAETOOMANYREFS +ETIMEDOUT WSAETIMEDOUT +ECONNREFUSED WSAECONNREFUSED +ELOOP WSAELOOP +ENAMETOOLONG WSAENAMETOOLONG +EHOSTDOWN WSAEHOSTDOWN +EHOSTUNREACH WSAEHOSTUNREACH +# Defined above because of conflict. +#ENOTEMPTY WSAENOTEMPTY +EPROCLIM WSAEPROCLIM +EUSERS WSAEUSERS +EDQUOT WSAEDQUOT +ESTALE WSAESTALE +EREMOTE WSAEREMOTE Added: trunk/cegcc/tools/errno/errno_h.awk =================================================================== --- trunk/cegcc/tools/errno/errno_h.awk (rev 0) +++ trunk/cegcc/tools/errno/errno_h.awk 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,41 @@ +BEGIN { + print "\ +#ifndef _LIB_CE_ERRNO_H\n\ +#define _LIB_CE_ERRNO_H\n\ +\n\ +#include <winerror.h>\n\ +\n\ +#define errno __liberrno_errno ()\n\ +#define __set_errno(ERR) SetLastError (ERR)\n\ +\n\ +#ifdef __cplusplus\n\ +extern \"C\" {\n\ +#endif\n\ +\n\ +int __liberrno_errno (void);\n\ +\n\ +char *strerror (int error);\n\ +void perror (const char *s);\n\ +\n\ +#ifdef __cplusplus\n\ +}\n\ +#endif\n\ +\n"; +} + +{ + errno = $1; + winerr = $2; + + if (errno != "" && substr (errno, 1, 1) != "#") + { + if (errno != prev_errno) + print "#define " errno " " winerr; + prev_errno = errno; + } +} + +END { + print ""; + print "#endif /* _LIB_CE_ERRNO_H */"; +} Property changes on: trunk/cegcc/tools/errno/errno_h.awk ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/errno/errno_str.awk =================================================================== --- trunk/cegcc/tools/errno/errno_str.awk (rev 0) +++ trunk/cegcc/tools/errno/errno_str.awk 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,12 @@ +BEGIN { +} + +{ + errno = $1; + winerr = $2; + # get tail beginning at $3 + msg=$0; for (i=1;i<3;i++) sub($i,"",msg); sub(/ */,"",msg) + + if (errno != "" && substr ($1, 1, 1) != "#" && msg != "") + print "case " winerr ": return " msg ";"; +} Property changes on: trunk/cegcc/tools/errno/errno_str.awk ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/errno/errno_tab.awk =================================================================== --- trunk/cegcc/tools/errno/errno_tab.awk (rev 0) +++ trunk/cegcc/tools/errno/errno_tab.awk 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,13 @@ +BEGIN { +} + +{ + winerr = $1; + errno = $2; + + if (errno != "" && substr (errno, 1, 1) != "#" && prev_winerr != winerr) + { + print "case " winerr ": return " errno ";"; + prev_winerr = winerr; + } +} Property changes on: trunk/cegcc/tools/errno/errno_tab.awk ___________________________________________________________________ Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-25 01:14:18
|
Revision: 1007 http://svn.sourceforge.net/cegcc/?rev=1007&view=rev Author: pedroalves Date: 2007-06-24 18:14:15 -0700 (Sun, 24 Jun 2007) Log Message: ----------- Initial import. * LICENSE, README, TODO, ChangeLog, Makefile, cwd.c cwd.h: New files. Added Paths: ----------- trunk/cegcc/tools/libcwd/ trunk/cegcc/tools/libcwd/ChangeLog trunk/cegcc/tools/libcwd/LICENSE trunk/cegcc/tools/libcwd/Makefile trunk/cegcc/tools/libcwd/README trunk/cegcc/tools/libcwd/TODO trunk/cegcc/tools/libcwd/cwd.c trunk/cegcc/tools/libcwd/cwd.h Added: trunk/cegcc/tools/libcwd/ChangeLog =================================================================== --- trunk/cegcc/tools/libcwd/ChangeLog (rev 0) +++ trunk/cegcc/tools/libcwd/ChangeLog 2007-06-25 01:14:15 UTC (rev 1007) @@ -0,0 +1,13 @@ +2007-06-25 Pedro Alves <ped...@po...> + + Initial import. + + * LICENSE, README, TODO, ChangeLog, Makefile, cwd.c cwd.h: New files. + + +Local Variables: +mode: change-log +left-margin: 8 +fill-column: 74 +version-control: never +End: Property changes on: trunk/cegcc/tools/libcwd/ChangeLog ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/libcwd/LICENSE =================================================================== --- trunk/cegcc/tools/libcwd/LICENSE (rev 0) +++ trunk/cegcc/tools/libcwd/LICENSE 2007-06-25 01:14:15 UTC (rev 1007) @@ -0,0 +1,25 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ Added: trunk/cegcc/tools/libcwd/Makefile =================================================================== --- trunk/cegcc/tools/libcwd/Makefile (rev 0) +++ trunk/cegcc/tools/libcwd/Makefile 2007-06-25 01:14:15 UTC (rev 1007) @@ -0,0 +1,62 @@ +TARGET=arm-wince-mingw32ce +LDFLAGS= +INCLUDES=-I. +CFLAGS=-O0 -g3 +WARNFLAGS=-Wall -Wextra + +ALLFLAGS=$(WARNFLAGS) $(CFLAGS) $(INCLUDES) + +CC=$(TARGET)-gcc +AR=$(TARGET)-ar + +LIBS = libcwd.a +TARGETS = $(LIBS) + +OBJECTS = cwd.o + +all: $(TARGETS) +libs: $(LIBS) + +.c.o: + $(CC) -c -o $@ $< $(ALLFLAGS) + +cwd.o: cwd.c cwd.h Makefile +stat.o: stat.o cwd.h Makefile +open.o: open.o cwd.h Makefile +rename.o: rename.o cwd.h Makefile +stat.o: stat.o cwd.h Makefile +tempnam.o: tempnam.o cwd.h Makefile +unlink.o: unlink.o cwd.h Makefile + +libcwd.a: $(OBJECTS) Makefile + rm -f $@ + $(AR) r $@ $(OBJECTS) + +install: + +clean: + rm -f $(LIBS) $(OBJECTS) + +dist: srcdist bindist + +srcdist: all + rm -rf $(distdir) + mkdir $(distdir) + chmod 755 $(distdir) + for i in $(SRCDIST_FILES); do \ + cp -p $(srcdir)/$$i $(distdir)/$$i ; \ + done + rm -f $(distdir).tar.gz + $(TAR) $(TARFLAGS)cf $(distdir)-src$(TARFILEEXT) $(distdir) + +bindist: all + rm -rf $(distdir) + mkdir $(distdir) + chmod 755 $(distdir) + for i in $(BINDIST_FILES); do \ + cp -p $(srcdir)/$$i $(distdir)/$$i ; \ + done + rm -f $(distdir).tar.gz + $(TAR) $(TARFLAGS)cf $(distdir)-bin$(TARFILEEXT) $(distdir) + +.PHONY: all install clean dist bindist srcdist Property changes on: trunk/cegcc/tools/libcwd/Makefile ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/libcwd/README =================================================================== --- trunk/cegcc/tools/libcwd/README (rev 0) +++ trunk/cegcc/tools/libcwd/README 2007-06-25 01:14:15 UTC (rev 1007) @@ -0,0 +1,22 @@ +This is a cwd lib for WinCE. + +This is a lib that serves as a porting aid. It provides chdir and +getcwd calls, thus a current working directory notion. + +Note that this lib is built as a static lib, so be careful with +linking the lib into several dlls/exe. Don't expect the same cwd +to be seen across dlls. For that to work, you'll need to build a +libcwd.dll. + +Have fun! + +Pedro Alves + +-- + +See the file LICENSE in the various directories, for a description of +the license the software is licensed in. + +REPORTING BUGS: +ce...@so... +pe...@po... Property changes on: trunk/cegcc/tools/libcwd/README ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/libcwd/TODO =================================================================== --- trunk/cegcc/tools/libcwd/TODO (rev 0) +++ trunk/cegcc/tools/libcwd/TODO 2007-06-25 01:14:15 UTC (rev 1007) @@ -0,0 +1,2 @@ + + * Add a mutex locking access to cwd. Property changes on: trunk/cegcc/tools/libcwd/TODO ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/libcwd/cwd.c =================================================================== --- trunk/cegcc/tools/libcwd/cwd.c (rev 0) +++ trunk/cegcc/tools/libcwd/cwd.c 2007-06-25 01:14:15 UTC (rev 1007) @@ -0,0 +1,320 @@ +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <wchar.h> + +#include <windows.h> + +#include "cwd.h" + +static wchar_t *XCEFixPathW (const wchar_t *wpathin, wchar_t *wpathout); +static wchar_t *XCECanonicalizePathW (wchar_t *target); +static DWORD XCEGetCurrentDirectoryW (DWORD dwSize, wchar_t *buf); + +#define COUNTOF(X) (sizeof (X) / sizeof ((X)[0])) +#define MIN(A, B) ((A) < (B) ? (A) : (B)) + +#define IS_DIRECTORY_SEP(X) (X == '\\') +#define IS_ANY_SEP(X) (X == '\\') + +/* Per process as on WinNT + ### TODO, we need a mutex here if we ever go multithread. */ + +static wchar_t _current_dirw[MAX_PATH+1] = L"\\"; +#define _CURRENTDIRW _current_dirw + +static DWORD +XCEGetFileAttributesW (const wchar_t *wfname) +{ + wchar_t wpath[MAX_PATH]; + DWORD dwRes; + + XCEFixPathW (wfname, wpath); + dwRes = GetFileAttributesW (wpath); + + return dwRes; +} + +static char * +XCEToUnixPath (char *s, int len) +{ + char *p; + + if (len < 0) + { + for(p = s; *p; p++) + if(*p == '\\') + *p = '/'; + } + else + { + int i; + for(i = 0; i < len ; i++) + if(s[i] == '\\') + s[i] = '/'; + } + + return s; +} + +static void +append_slash_if_needed (wchar_t* wbuf) +{ + int len = wcslen (wbuf); + if (len > 0 + && wbuf[len - 1] != '\\' + && wbuf[len - 1] != '/') + wcscat (wbuf, L"\\"); +} + +static wchar_t * +XCEFixPathW (const wchar_t *wpathin, wchar_t *wpathout) +{ + wchar_t wdir[MAX_PATH+1]; + wchar_t *p; + + wpathout[0] = 0; + append_slash_if_needed (wpathout); + + if(wpathin[0] != '\\' && wpathin[0] != '/') + { + XCEGetCurrentDirectoryW (sizeof(wdir), wdir); + wcscat (wpathout, wdir); + append_slash_if_needed (wpathout); + } + + wcscat (wpathout, wpathin); + + for(p = wpathout; *p; p++) + { + if(*p == '/') + *p = '\\'; + } + + /* don't allow slash at end of directory name... */ + if(p[-1] == '\\' && p != wpathout + 1) + p[-1] = 0; + + /* now remove . and .. */ + XCECanonicalizePathW (wpathout); + + return wpathout; +} + +static wchar_t * +XCECanonicalizePathW (wchar_t *target) +{ + wchar_t *p = target; + wchar_t *o = target; + + while (*p) + { + if (!IS_DIRECTORY_SEP (*p)) + { + *o++ = *p++; + } + else if (IS_DIRECTORY_SEP (p[0]) + && p[1] == '.' + && (IS_DIRECTORY_SEP (p[2]) + || p[2] == 0)) + { + /* If "/." is the entire filename, keep the "/". Otherwise, + just delete the whole "/.". */ + if (o == target && p[2] == '\0') + *o++ = *p; + p += 2; + } + else if (IS_DIRECTORY_SEP (p[0]) && p[1] == '.' && p[2] == '.' + /* `/../' is the "superroot" on certain file systems. */ + /* disabled this test, as it wasn't filtering '/..' because of it. + cegcc should also have the same problem. */ + /* && o != target */ + && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0)) + { + while (o != target && (--o) && !IS_DIRECTORY_SEP (*o)) + ; + /* Keep initial / only if this is the whole name. */ + if (o == target && IS_ANY_SEP (*o) && p[3] == 0) + ++o; + p += 3; + } + else + { + *o++ = *p++; + } + } + + *o = 0; + + return target; +} + +static DWORD +XCEGetCurrentDirectoryW (DWORD dwSize, wchar_t *buf) +{ + size_t len = wcslen(_CURRENTDIRW); + if (dwSize == 0 && buf == 0) + return len+1; + wcsncpy (buf, _CURRENTDIRW, dwSize - 1); + if (dwSize > len) + return len; + else + return len+1; +} + +static DWORD +XCEGetCurrentDirectoryA (DWORD dwSize, char *buf) +{ + DWORD dwLen; + wchar_t wbuf[MAX_PATH+1]; + + dwLen = XCEGetCurrentDirectoryW (dwSize, wbuf); + if (dwSize == 0 && buf == 0) + return dwSize; + WideCharToMultiByte (CP_ACP, 0, wbuf, -1, + buf, MIN(dwLen, dwSize), NULL, NULL); + buf[MIN(dwLen, dwSize)] = 0; + return dwLen; +} + +static BOOL +XCESetCurrentDirectoryW (const wchar_t *wdir) +{ + DWORD dwAttr; + wchar_t wtmp[MAX_PATH]; + + int wlen = wcslen (wdir); + if (wlen > (MAX_PATH - 1)) + return 0; + else if (wlen > 0 + && !(wdir[wlen-1] == '\\' || wdir[wlen-1] == '/') + && wlen > (MAX_PATH - 2)) + return 0; + + /* Oh great... There is some code generation bug in mingw32ce. Inlining + the call hides the problem. */ + // XCEFixPathW (wdir, wtmp); + const wchar_t *wpathin = wdir; + wchar_t *wpathout = wtmp; + { + wchar_t wdir[MAX_PATH+1]; + wchar_t *p; + + wpathout[0] = 0; + + if(wpathin[0] != '\\' && wpathin[0] != '/') + { + XCEGetCurrentDirectoryW (sizeof(wdir), wdir); + wcscat (wpathout, wdir); + append_slash_if_needed (wpathout); + } + + wcscat (wpathout, wpathin); + + for(p = wpathout; *p; p++) + { + if(*p == '/') + *p = '\\'; + } + + /* Don't allow slash at end of directory name... */ + if(p[-1] == '\\' && p != wpathout + 1) + p[-1] = 0; + + /* Now remove . and .. */ + XCECanonicalizePathW (wpathout); + } + + if((dwAttr = XCEGetFileAttributesW (wtmp)) == 0xFFFFFFFF) + return FALSE; + + if((dwAttr & FILE_ATTRIBUTE_DIRECTORY) == 0) + { +// errno = ENOTDIR; + return FALSE; + } + + wcscpy (_CURRENTDIRW, wtmp); + return TRUE; +} + +static BOOL +XCESetCurrentDirectoryA (const char *dir) +{ + wchar_t wdir[MAX_PATH]; + int len = strlen(dir); + if (len > (MAX_PATH - 1)) + return 0; + else if (len>0 + && !(dir[len-1] == '\\' || dir[len-1] == '/') + && len > (MAX_PATH - 2)) + return 0; + + MultiByteToWideChar (CP_ACP, 0, dir, -1, wdir, COUNTOF (wdir)); + return XCESetCurrentDirectoryW (wdir); +} + +int +_chdir (const char *path) +{ + char fpath[MAX_PATH+1]; + + if (path == NULL || strlen (path) == 0) + { + /* errno? */ + return -1; + } + + if (!XCESetCurrentDirectoryA (path)) + return -1; + + XCEGetCurrentDirectoryA (MAX_PATH + 1, fpath); + XCEToUnixPath (fpath, -1); + return 0; +} + +char * +_getcwd (char *buf, int size) +{ + int len; + char *alloced = NULL; + + if (buf == NULL || size == 0) + { + size = MAX_PATH + 1; + buf = alloced = malloc (size); + if (!buf) + return NULL; + } + + len = XCEGetCurrentDirectoryA ((DWORD) size, buf); + + if (len > size) + { + XCEToUnixPath (buf, size - 1); + return NULL; + } + + if (len == 0) + { + if (alloced != NULL) + free (alloced); + return NULL; + } + + XCEToUnixPath (buf, -1); + return buf; +} + +int +chdir (const char *path) +{ + return _chdir (path); +} + +char * +getcwd (char *buf, int size) +{ + return _getcwd (buf, size); +} Property changes on: trunk/cegcc/tools/libcwd/cwd.c ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/libcwd/cwd.h =================================================================== --- trunk/cegcc/tools/libcwd/cwd.h (rev 0) +++ trunk/cegcc/tools/libcwd/cwd.h 2007-06-25 01:14:15 UTC (rev 1007) @@ -0,0 +1,19 @@ +#ifndef __LIB_CE_CWD_H_ +#define __LIB_CE_CWD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> + +extern char *getcwd (char *buf, int size); +extern char *_getcwd (char *buf, int size); +extern int chdir (const char *path); +extern int _chdir (const char *path); + +#ifdef __cplusplus +} +#endif + +#endif /* __LIB_CE_CWD_H_ */ Property changes on: trunk/cegcc/tools/libcwd/cwd.h ___________________________________________________________________ Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-25 01:15:45
|
Revision: 1008 http://svn.sourceforge.net/cegcc/?rev=1008&view=rev Author: pedroalves Date: 2007-06-24 18:15:40 -0700 (Sun, 24 Jun 2007) Log Message: ----------- Initial import. * LICENSE, README, TODO, ChangeLog, Makefile, rcp.c, FindFileA.c, Readme_org.txt: New files. Added Paths: ----------- trunk/cegcc/tools/rcp/ trunk/cegcc/tools/rcp/ChangeLog trunk/cegcc/tools/rcp/FindFileA.c trunk/cegcc/tools/rcp/LICENSE trunk/cegcc/tools/rcp/Makefile trunk/cegcc/tools/rcp/README trunk/cegcc/tools/rcp/Readme_org.txt trunk/cegcc/tools/rcp/TODO trunk/cegcc/tools/rcp/rcp.c Added: trunk/cegcc/tools/rcp/ChangeLog =================================================================== --- trunk/cegcc/tools/rcp/ChangeLog (rev 0) +++ trunk/cegcc/tools/rcp/ChangeLog 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,14 @@ +2007-06-25 Pedro Alves <ped...@po...> + + Initial import. + + * LICENSE, README, TODO, ChangeLog, Makefile, rcp.c, FindFileA.c, + Readme_org.txt: New files. + + +Local Variables: +mode: change-log +left-margin: 8 +fill-column: 74 +version-control: never +End: Property changes on: trunk/cegcc/tools/rcp/ChangeLog ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp/FindFileA.c =================================================================== --- trunk/cegcc/tools/rcp/FindFileA.c (rev 0) +++ trunk/cegcc/tools/rcp/FindFileA.c 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,91 @@ +// findfile.c +// +// Time-stamp: <12/02/01 14:42:40 keuchel@keuchelnt> + +#include <wchar.h> + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#define COUNTOF(X) (sizeof (X)/sizeof ((X)[0])) + +HANDLE WINAPI +FindFirstFileA (const char *lpName, LPWIN32_FIND_DATAA lpfd) +{ + HANDLE hFind; + WIN32_FIND_DATAW fdw; + wchar_t lpNameNew[MAX_PATH]; + + MultiByteToWideChar(CP_ACP, 0, lpName, -1, lpNameNew, COUNTOF (lpNameNew)); + + hFind = FindFirstFileW (lpNameNew, &fdw); + + if(hFind != INVALID_HANDLE_VALUE) + { + lpfd->dwFileAttributes = fdw.dwFileAttributes; + lpfd->ftCreationTime = fdw.ftCreationTime; + lpfd->ftLastAccessTime = fdw.ftLastAccessTime; + lpfd->ftLastWriteTime = fdw.ftLastWriteTime; + lpfd->nFileSizeHigh = fdw.nFileSizeHigh; + lpfd->nFileSizeLow = fdw.nFileSizeLow; + +#ifdef __COREDLL__ + lpfd->dwReserved0 = fdw.dwOID; +#endif + + WideCharToMultiByte (CP_ACP, 0, + fdw.cFileName, -1, + lpfd->cFileName, + COUNTOF (lpfd->cFileName), + NULL, NULL); + + // not in wince... + lpfd->cAlternateFileName[0] = 0; + } + + return hFind; +} + +BOOL WINAPI +FindNextFileA (HANDLE hFind, LPWIN32_FIND_DATAA lpfd) +{ + WIN32_FIND_DATAW fdw; + BOOL res; + + // is this needed? + fdw.dwFileAttributes = lpfd->dwFileAttributes; + fdw.ftCreationTime = lpfd->ftCreationTime; + fdw.ftLastAccessTime = lpfd->ftLastAccessTime; + fdw.ftLastWriteTime = lpfd->ftLastWriteTime; + fdw.nFileSizeHigh = lpfd->nFileSizeHigh; + fdw.nFileSizeLow = lpfd->nFileSizeLow; +#ifdef __COREDLL__ + fdw.dwOID = lpfd->dwReserved0; +#endif + + res = FindNextFileW(hFind, &fdw); + + if(res == TRUE) + { + lpfd->dwFileAttributes = fdw.dwFileAttributes; + lpfd->ftCreationTime = fdw.ftCreationTime; + lpfd->ftLastAccessTime = fdw.ftLastAccessTime; + lpfd->ftLastWriteTime = fdw.ftLastWriteTime; + lpfd->nFileSizeHigh = fdw.nFileSizeHigh; + lpfd->nFileSizeLow = fdw.nFileSizeLow; + +#ifdef __COREDLL__ + lpfd->dwReserved0 = fdw.dwOID; +#endif + + WideCharToMultiByte(CP_ACP, 0, + fdw.cFileName, -1, + lpfd->cFileName, + COUNTOF(lpfd->cFileName), + NULL, NULL); + + lpfd->cAlternateFileName[0] = 0; + } + + return res; +} Property changes on: trunk/cegcc/tools/rcp/FindFileA.c ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp/LICENSE =================================================================== --- trunk/cegcc/tools/rcp/LICENSE (rev 0) +++ trunk/cegcc/tools/rcp/LICENSE 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,27 @@ +This tool was written based on the rcp extension to +"rshd - Remote Shell Daemon for Windows NT version 1.6" written by +Silviu C. Marghescu (http://www.cs.umd.edu/~silviu). The rcp +extension was written by Gary Doss (gd...@rp...). + +See the Readme_org.txt file for the original copyright notice, and the +original disclaimer. + +The changes made to the original files are also covered by the +following conditions: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ Added: trunk/cegcc/tools/rcp/Makefile =================================================================== --- trunk/cegcc/tools/rcp/Makefile (rev 0) +++ trunk/cegcc/tools/rcp/Makefile 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,74 @@ +TARGET=arm-wince-mingw32ce +CFLAGS=-O0 -g3 +WARNFLAGS=-Wall -Wextra + +INCLUDES=-I../errno -I../libcwd +LDFLAGS=-L../errno -L../libcwd +LIBS=-lcwd -lerrno + +ALLFLAGS=$(CFLAGS) $(INCLUDES) $(WARNFLAGS) + +CC=$(TARGET)-gcc +STRIP=$(TARGET)-strip + +BINS = rcp_unstripped.exe +STRIPPED_BINS = rcp.exe + +TARGETS = $(STRIPPED_BINS) + +srcdir=. +distdir=rcp-0.1.0 +TAR = tar +TARFLAGS = z +TARFILEEXT = .tar.gz + +SRCDIST_FILES=\ + rcp.c Makefile README TODO COPYING ChangeLog + +BINDIST_FILES=\ + rcp.exe + +OBJECTS=rcp.o FindFileA.o + +all: $(TARGETS) +bins: $(BINS) + +.c.o: + $(CC) -o $@ $< -c $(ALLFLAGS) + +rcp_unstripped.exe: $(OBJECTS) Makefile + $(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(ALLFLAGS) $(LIBS) + +rcp.exe: rcp_unstripped.exe + $(STRIP) $< -o $@ + +download: rcp.exe + pcp rcp.exe ":/rcp.exe" + +clean: + rm -f $(BINS) $(STRIPPED_BINS) $(OBJECTS) + +dist: srcdist bindist + +srcdist: all + rm -rf $(distdir) + mkdir $(distdir) + chmod 755 $(distdir) + for i in $(SRCDIST_FILES); do \ + cp -p $(srcdir)/$$i $(distdir)/$$i ; \ + done + rm -f $(distdir).tar.gz + $(TAR) $(TARFLAGS)cf $(distdir)-src$(TARFILEEXT) $(distdir) + +bindist: all + rm -rf $(distdir) + mkdir $(distdir) + chmod 755 $(distdir) + for i in $(BINDIST_FILES); do \ + cp -p $(srcdir)/$$i $(distdir)/$$i ; \ + done + rm -f $(distdir).tar.gz + $(TAR) $(TARFLAGS)cf $(distdir)-bin$(TARFILEEXT) $(distdir) + + +.PHONY: all install download clean dist bindist srcdist Property changes on: trunk/cegcc/tools/rcp/Makefile ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp/README =================================================================== --- trunk/cegcc/tools/rcp/README (rev 0) +++ trunk/cegcc/tools/rcp/README 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,26 @@ + README for rcp for Windows CE + +This directory contains rcp for Windows CE. + +This tool was written based on the rcp extension to +"rshd - Remote Shell Daemon for Windows NT version 1.6" written by +Silviu C. Marghescu (http://www.cs.umd.edu/~silviu). The rcp +extension was written by Gary Doss (gd...@rp...). + +The rcp part was totally separated from Silviu's rshd, and converted +to read/write from/to stdin/stdout. It is supposed to be invoked from +rshd for WinCE with stdin/stdout/stderr redirected, much like a unix +version of rcp would do. + +To build make sure you have the mingw32ce toolchain on your path, and +type make. + +Have fun! + +Pedro Alves + +-- + +REPORTING BUGS: +ce...@so... +pe...@po... Property changes on: trunk/cegcc/tools/rcp/README ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp/Readme_org.txt =================================================================== --- trunk/cegcc/tools/rcp/Readme_org.txt (rev 0) +++ trunk/cegcc/tools/rcp/Readme_org.txt 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,241 @@ +rshd - Remote Shell Daemon for Windows NT version 1.6 + +Written by Silviu C. Marghescu (http://www.cs.umd.edu/~silviu) +Copyright (C) 1996 Silviu C. Marghescu, Emaginet, Inc. +All Rights Reserved. + +Password functionality added by Ashley M. Hopkins (http://www.csee.usf.edu/~amhopki2) + +rshd is free software; you can redistribute it in its entirety +in any form you like. If you find any bugs, feel free to send me an +email at si...@em.... If you have added new features to rshd, +please send me all the source code modifications, including the version +of rshd that you are based on. Your additions may benefit other users. + + +Disclaimer +========== + +rshd is distributed hoping that it will be useful, but WITHOUT ANY WARRANTY; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. + +Good data processing procedure dictates that any program be +thoroughly tested with non-critical data before relying on it. +The user must assume the entire risk of using the program. +THE AUTHOR SHALL NOT BE HELD LIABLE FOR ANY KIND OF DAMAGES OR CLAIMS THAT +DIRECTLY OR INDIRECTLY RESULT FROM USING THIS SOFTWARE. + + +Description +=========== + +rshd is a multithreaded daemon service that listens for connections on port +514 (tcp port for the shell/cmd protocol), runs commands passed by clients and sends +back the results. It was my experience that the rshd service included in the +Windows NT Resource Kit does not fully follow the BSD specification for the rsh protocol; +it works fine with the rsh client in NT, but other clients fail to connect. +This implementation of rshd tries to get as close as possible to the BSD specs +(http://www.bsdi.com). + +As of version 1.5, rshd comes with RCP server support, thanks to Gary Doss +(gd...@rp...); any problem/question concerning the rcp +part of rshd would be better answered by him. + +Important note: rshd was designed and implemented to be convenient and reliable, +rather than tightly secure. A client trying to connect to rshd will have to pass +a security clearance process, but rshd is probably far from a secure service. +If security is of major concern across your network, you should be very careful +when using this service. My target for rshd was a closed network, or a network +guarded by a firewall. + + +Requirements +============ + +o An Intel processor based machine running Microsoft Windows NT and TCP/IP. +o Window Socket DLL installed properly (version 1.1 or higher). + + +Installation +============ + +This package contains the following files: + readme.txt - this file + rshd.exe - the rshd daemon executable +The source distribution also contains: + rshd.cpp - the C++ source file (actually mostly C, but I prefer to define + variables when I really need them; plus, I like the // comments) + rshd_rcp.cpp - the C++ source file for the RCP service + service.cpp, service.h - the service routines (many thanks to Craig Link, + Microsoft for including the Service project in the samples) + rshd.ide - the project file for Borland C++ 5.0 users + rshd.mak - the project file for Microsoft Visual C++ 2.0 + + +Running rshd +============ + +In this new version, rshd runs as a service. You also have the option of running rshd +as a command line application (see "-d" later on). In order to get the service up and +running, you will have to complete the following steps: +1. install the service: + rhsd -install +2. start the service: + net start rshd +That's it! Stopping the service is as easy as starting it: + net stop rshd +Should you decide rshd is not the way to go: + rshd -remove +Starting/stopping the service can also be done through the "Services" Control Panel +applet; just look for the RSHD Daemon service. + +Note that if the applications you are running require user credentials, you should +run the service under the corresponding user account. + +Command line options: +-install installs the rshd service +-remove removes the rshd service + +The following command line options have been inherited from the previous, interactive +versions. I don't know if they'll be useful if you decide to run rshd as a service. +I haven't figured out yet how to run the service with command line options, therefore +the '-r' is set by default. + +-d enables debugging messages and allows you to run rshd as a command line process. Good + for those days when nothing works... +-1 no stdout redirection. By default, rshd will redirect the output of your + command into a temporary file and send the result back thru the client + socket. If however you are not interested in the output, or the command + is already redirected, this option will prevent stdout redirection. + Note that the option is global, meaning it will disable redirection + regardless of the commands you're passing... +-2 no stderr redirection. Same as '-1', but for stderr. At this point it + should be noted that under the BSD rshd specification, the client can pass + an auxillary tcp port number that the daemon can use to send the stderr + output back. The rshd will connect to that port if provided and send + back the stderr, unless this option is given. If no alternative stderr port + is provided, rshd will use the main socket for both stdout and stderr. +-4 4DOS command shell. Different shells and different operating systems have + different ways of redirecting output, especially for the standard error stream. + rshd was tested in the following configurations: CMD.EXE and 4NT.EXE on + Windows NT; COMMAND.COM and 4DOS.COM on Windows 95. If you're running 4DOS + on Windows 95, make sure you set the '-4' command parameter, otherwise the + stderr redirection will fail. +-s stronger security enabled. By default, when the client credentials can't + be checked, rshd assumes it to be friendly and runs the command. If that + creates security concernes, this option will accept the connection to a client + only if everything checks out. +-r no .rhosts checking. Per BSD rshd specification, rshd loads the + <windir>\.rhosts file and builds a list of trusted hosts. + Any further connections will be accepted only from a host in the + list. '-r' disables this checking. Note that this is a major security + issue: if your network is not closed or guarded by a firewall, anybody + can connect thru the rsh protocol and run commands on your machines. + Use this option only if you know exactly who is running what across your + network! +-p password option enabled. User will be prompted to enter a password after start of + the daemon. To enable rsh commands to execute on the daemon with this enabled user + must enter password from the command line in the rsh command between the hostname and the command. (rsh hostname password command) + The password option does not affect the rcp command. +-v displays the rshd version. +-h help screen. + +RCP usage: + Valid rcp requests are in the form: + rcp -t [-d] [-r] [-p] target + rcp -f [r] [-p] target + NOTE: The -p option is being ignored since there is not a good + correlation between UNIX and NT when it comes to file + permissions and ownership. + +I have tested rshd with the following rsh clients: WinRSH (both 16 and 32 bit +versions; this was the client I needed to use and didn't work with the Resource +Kit implementation of rshd); NT client of rsh; SunOS client of rsh. The main +difference between WinRSH and the other rsh clients is that WinRSH does not open +a stderr additional port; rshd will send both the stdout and stderr output thru +the main socket. + + +Security considerations +======================= + +As stated above, security was not the main issue while implementing rshd. The +daemon still tries to authenticate the remote user/host, but the authentication +process is not fully implemented and should not be considered secure. +In this version, only host authentication is implemented. If not disabled (see +the '-r' switch), an .rhosts mechanism is used: the remote host name is searched +in the .rhosts file; if it is not found, the connection is refused. +Sometimes, rshd does not have enough information to decide whether the connection +is secure or not (e.g. cannot determine the remote host name); in this cases, by +default, the connection is accepted, unless the '-s' switch is on. The '-s' switch +will enable a tighter security: only fully recognized clients will be able to connect. + +The password functionality added by Ashley M. Hopkins enables another layer of security by requiring that the user enter a password. This option can be used in conjunction with the .rhosts file or with the .rhosts checking disabled (-r). + +To allow compatibility across NT/95 platforms, the required path for the .rhosts file +(if you decide to use the feature) is: <windir>\.rhosts, where <windir> is your +Windows root directory as reported by the WINDIR environment variable. + + +Rebuilding rshd +=============== + +You probably have the sources already... I've built rshd with both Visual C++ +and Borland C++; the .ide file is the Borland project and the .mak is the one +you need for Visual C++. Make sure you define the appropriate macro (first lines +in rshd.cpp define either VISUALCPP or BORLANDCPP). + + +Known problems +============== + +Some rsh clients open an additional connection for the stderr output. There is a +known problem/feature in Microsoft's implementation of TCP/IP that causes closed +connections to linger on for 2 maximum segment lives (4 minutes). Within the timeout +period, the local port is unusable. For this reason, rshd has a mechanism for port +resolution that tries to assign local ports in a round-robin fashion. +It is not a clean solution, but it works for the time being (there is still a problem +if rshd is restarted, since it begins assigning ports from 1023; if those ports are +taken by TIME_WAIT connections, they'll be unusable). A way of reducing the timeout +period to less than 4 minutes is described in Microsoft's Knowledge Base article Q149532: + +***************************************************************************************** +A new registry has been added to TCP/IP to allow the TIME-WAIT state to be configurable. +This will allow TCP/IP users to free closed connection resources more quickly. + +The new registry entry is: + + TcpTimedWaitDelay + Key: Tcpip\Parameters + Value Type: REG_DWORD - Time in seconds + Valid Range: 30-300 (decimal) + Default: 0xF0 (240 decimal) +***************************************************************************************** + + +Also, very long command lines (e.g. more than 1024 characters) can cause rshd to +crash. Still working on it. + +For complex commands (e.g. "comm1 | comm2"), to achieve correct redirection, the whole +command needs to be enclosed in parenthesis (e.g. (comm1 | comm2) ). However, that creates +problems on some machines (errors have been reported on Windows 95, running under command.com). +Things go smoothly though if you have 4NT or 4DOS (use the '-4' flag then). + + + +Whether you have good or bad comments, improvements and suggestions, I would like +to hear from you at si...@em.... + + +Bug fixes, improvements +======================= + +Gary Doss (gd...@rp...) has had a major contribution to rshd, +with the RCP support and some pretty good bug fixes. + +Barbara Dawkins (bda...@rp...) has improved Gary's RCP support +and fixed a couple of bugs. + + +Ashley Hopkins (amh...@cs...) has added the password option to the rshd to improve security of this daemon. Additionally a bug has been fixed to allow the transfer of executable files. \ No newline at end of file Property changes on: trunk/cegcc/tools/rcp/Readme_org.txt ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp/TODO =================================================================== --- trunk/cegcc/tools/rcp/TODO (rev 0) +++ trunk/cegcc/tools/rcp/TODO 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,5 @@ + +* Rewrite the ParseTarget, NextTarget and CloseTarget function to use + _findfirst, or dirent or something else. + +* Convert rcp_main to use getopt. Property changes on: trunk/cegcc/tools/rcp/TODO ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp/rcp.c =================================================================== --- trunk/cegcc/tools/rcp/rcp.c (rev 0) +++ trunk/cegcc/tools/rcp/rcp.c 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,1002 @@ +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* Follows the original Copyright and disclaimer statements of the + original package. */ + +////////////////////////////////////////////////////////////////////////// +// +// rshd_rcp.cpp +// +// This file contains code which will extend rshd to handle rcp +// requests. +// +// Author: Gary L. Doss NCR Corporation +// Date: December 16, 1996 +// +////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////// +// +// rsh daemon for Windows NT/95 +// (c) 1996 Silviu Marghescu - Emaginet, Inc. +// +// +// This program is free software; you can redistribute and/or modify +// it. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// +// +// rshd - Remote Shell Daemon for Windows NT/95 +// Author: Silviu C. Marghescu (http://www.cs.umd.edu/~silviu) +// Date: May 16, 1996 +// +////////////////////////////////////////////////////////////////////////// + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <io.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <dirent.h> +#include <stdarg.h> + +#include <windows.h> + +#include <cwd.h> + +static FILE * +get_logfile (void) +{ +#if 0 + static FILE* logger = NULL; + + if (logger == NULL) + { + char buf[200]; + sprintf (buf, "rcp-%08x", (unsigned) GetCurrentProcessId ()); + logger = fopen (buf, "a+"); + } + return logger; +#else + return stderr; +#endif +} + +static int debugFlag = 0; + +static void +error (const char *message) +{ + FILE* f = get_logfile (); + fprintf (f, "%s\n", message); + fflush (f); +} + +static void +debug (const char *format, ...) +{ + if (debugFlag) + { + FILE* f = get_logfile (); + va_list ap; + va_start (ap, format); + vfprintf (f, format, ap); + fflush (f); + va_end (ap); + } +} + +/* This is the size of the buffer used with rcp */ +#define RCP_BUFFER_SIZE 8192 +/* This is a delay time in milliseconds to wait after sending an error + condition to the remote hosts during an rcp. */ +#define RCP_ERR_DELAY 1000 + +/* Several of the messages sent in the rcp protocol are single + byte ( 0x00 ) or are text messages terminated by a ('\n'). + This routine reads the message a single byte at a time and + checks for the appropriate termination condition. + BUFF is the buffer to hold the data. + BLEN is the length of the buffer. + returns -1 if recv fails or number of characters received on SUCCESS. */ +static int +RcpReceive (char *buff, int blen) +{ + int i; + int rlen; + char tchar; + + i = 0; + buff[0] = 0; + do + { + rlen = read (fileno (stdin), &buff[i], 1); + if (rlen == -1) + { + error ("Cannot receive client data."); + return rlen; + } + if (debugFlag) + { + if (!rlen) + fprintf (stderr, "...got %d chars. \n", rlen); + else + fprintf (stderr, "...got %d chars. [%c]\n", rlen, buff[i]); + } + tchar = buff[i]; + i++; + if (i > blen) + { + /* The buffer has overflowed. */ + SetLastError (WSAEMSGSIZE); + return -1; + } + } + while (tchar != '\n' && tchar != '\0'); + + return i; +} + +/* ParseTarget is the first step in processing environment + variables and wild card characters that may exists in + the target specification of the rcp command. All + environment variables are expanded and a find is initiated + to handle the wild card characters ( ? and * ). + HFILE is a pointer to a file handle. The file handle is used + by the calling process to obtain more files associated with the target. + TARGET is the target file/directory that needs to be expanded. + BDIR is a flag will be set to TRUE if the TARGET is a directory and + FALSE if it is a file. + Return TRUE if there are possibly more files that match the target + and FALSE if this is the only file that matches. + + The wildcard characters are only valid if used in the last item + in the path specified by Target. + + See Also NextTarget and CloseTarget. */ +static BOOL +ParseTarget (HANDLE * hFile, char *Target, BOOL *bDir) +{ + char strPath[MAX_PATH]; +#if 0 + long lLen; +#endif + WIN32_FIND_DATAA wfdFileData; + BOOL bMoreFiles = FALSE; + char *strLastSlash; + char strDirectory[MAX_PATH]; + struct stat statbuf; + + /* TARGET may contain: + Environment Variables: %name% + Wild Card Characters: ? and * */ +#if 0 + lLen = ExpandEnvironmentStrings (Target, strPath, MAX_PATH); + + if (debugFlag) + fprintf (stderr, "The expanded path is %d chars %d: %s\n", lLen, + GetLastError (), strPath); +#else + strcpy (strPath, Target); +#endif + /* Determine the directory name for the expanded target. */ + strLastSlash = strchr (strPath, '/'); + while (strLastSlash != NULL) + { + *strLastSlash = '\\'; + strLastSlash++; + strLastSlash = strrchr (strLastSlash, '/'); + } + + strLastSlash = strrchr (strPath, '\\'); + if ((strLastSlash == NULL) || (strLastSlash == strPath)) + strDirectory[0] = 0; + else + { + strncpy (strDirectory, strPath, (long) (strLastSlash - strPath)); + strDirectory[(long) (strLastSlash - strPath)] = 0; + strcat (strDirectory, "\\"); + } + + /* If the target has wildcards, process them. */ + if ((strchr (strPath, '?') != NULL) || (strchr (strPath, '*') != NULL)) + { + *hFile = FindFirstFileA (strPath, &wfdFileData); + if (*hFile != INVALID_HANDLE_VALUE) + { + bMoreFiles = TRUE; + if (wfdFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + *bDir = TRUE; + /* Ignore directories "." and ".." */ + while (!(strcmp (wfdFileData.cFileName, ".")) || + !(strcmp (wfdFileData.cFileName, ".."))) + { + if (!FindNextFileA (*hFile, &wfdFileData)) + { + /* Handle error. */ + Target[0] = 0; + *bDir = FALSE; + return FALSE; + } + *bDir = + (wfdFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + ? TRUE : FALSE; + } + } + else + *bDir = FALSE; + + sprintf (Target, "%s%s", strDirectory, wfdFileData.cFileName); + } + else + { + Target[0] = 0; + *bDir = FALSE; + return FALSE; + } + } + else + { + /* Check to see if Target is a file or a directory. */ + strcpy (Target, strPath); + if (stat (Target, &statbuf) != 0) + return FALSE; + else + *bDir = (statbuf.st_mode & S_IFDIR) ? TRUE : FALSE; + } + return bMoreFiles; +} + +/* This function gets the next available target that matches + the specification passed to ParseTarget for the specified + HANDLE. HFILE is a HANDLE returned from call to ParseTarget. + BDIR is a flag that will be set to TRUE if the TARGET is a + directory and to FALSE if it is a regular file. + Returns NULL if no more matches exist, of a pointer to target + name if a match is found. + + Assumptions: + The pointer returned by NextTarget should never be deleted. + NextTarget is always called after ParseTarget. + No target names will be larger than MAX_PATH. + + See Also: ParseTarget, CloseTarget. */ +static char * +NextTarget (HANDLE hFile, BOOL * bDir) +{ + static char Target[MAX_PATH]; + WIN32_FIND_DATAA wfdFileData; + + /* Make sure the handle is not bad. */ + if (hFile == INVALID_HANDLE_VALUE) + { + *bDir = FALSE; + return NULL; + } + + if (FindNextFileA (hFile, &wfdFileData)) + { + /* A match was found. */ + if (wfdFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + *bDir = TRUE; + /* Ignore directories "." and "..". */ + while (!(strcmp (wfdFileData.cFileName, ".")) || + !(strcmp (wfdFileData.cFileName, ".."))) + { + if (!FindNextFileA (hFile, &wfdFileData)) + { + /* Handle error. */ + Target[0] = 0; + *bDir = FALSE; + return NULL; + } + if (wfdFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + *bDir = TRUE; + else + *bDir = FALSE; + } + } + else + *bDir = FALSE; + + sprintf (Target, "%s", wfdFileData.cFileName); + } + else + { + Target[0] = 0; + *bDir = FALSE; + return NULL; + } + return (Target); +} + +/* Terminate the search for target matches that was initiated + in the call to ParseTarget. HFILE is a HANDLE returned from + the call to ParseTarget. + + Assumptions: + CloseTarget must always be used to close the find initiated by + ParseTarget. + There are no more matches to a target when NextTarget returns + NULL. + + See Also: ParseTarget, NextTarget. */ +void +CloseTarget (HANDLE hFile) +{ + if (hFile != INVALID_HANDLE_VALUE) + FindClose (hFile); + return; +} + +/* This functions processes an rcp request to send files to + a remote system. TARGET is the target specified in the rcp + request. BRECURSIVE specified that this request must recurse + the sub-directories of the specfied target. + + Assumptions: + All files sent are read as BINARY files. This prevents + the translation of CR-LF to LF and preserves the size of the file + and the data contained in it. */ +void +RcpSvrSend (const char *Target, BOOL bRecursive) +{ + char buff[RCP_BUFFER_SIZE + 1]; + int blen = RCP_BUFFER_SIZE; + int FileId; + int nFileSize; + int nBytesRead; + int nBytesSent; + int dwBytes; + int nValue; + BOOL bMoreFiles; + HANDLE hFile = INVALID_HANDLE_VALUE; + char expTarget[MAX_PATH]; + char *Target2; + char *FileName; + BOOL bDir; + BOOL bTarget; + BOOL bProcessing; + struct _stat statbuf; + + debug ("sending %s\n", Target); + + /* Copy the target to a buffer we know will hold MAX_PATH. */ + strcpy (expTarget, Target); + /* Check the target for environment variables and wild cards. */ + bMoreFiles = ParseTarget (&hFile, expTarget, &bDir); + bTarget = bDir; + + if (!bRecursive & bDir) + { + /* Error condition. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s: Not a plain file\n", expTarget); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + debug ("sending %s\n", expTarget); + + if (access (expTarget, 02) != 0) + { + debug ("error\n"); + /* Error condition */ + buff[0] = 1; + if (errno == ENOENT) + sprintf (&buff[1], "rcp: %s: No such file or directory\n", expTarget); + else + sprintf (&buff[1], "rcp: %s: Permission Denied\n", expTarget); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + debug ("waiting for '\\0'\n"); + + /* Receive data from the client expecting 0x00. */ + if ((dwBytes = RcpReceive (buff, blen)) == -1) + { + error ("Cannot receive client data."); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + debug ("waiting for '\\0' : done\n"); + + if (buff[0] != 0) + { + error ("Remote system failed."); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + bProcessing = TRUE; + Target2 = expTarget; + while (Target2 != NULL) + { + if (bDir) + { + /* Notify remote system to create a directory. */ + FileName = strrchr (Target2, '\\'); + if (FileName == NULL) + FileName = Target2; + else + FileName++; + + sprintf (buff, "D0755 0 %s\n", FileName); + + if (write (fileno (stdout), buff, strlen (buff)) < 1) + { + error ("Error sending directory status."); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + chdir (Target2); + RcpSvrSend ("*", bRecursive); + chdir (".."); + } + else + { + FileName = strrchr (Target2, '\\'); + if (FileName == NULL) + FileName = Target2; + else + { + *FileName = 0; + chdir (Target2); + FileName++; + } + /* Open the file for reading. */ + FileId = _open (FileName, O_RDONLY | O_BINARY, S_IWRITE); + if (FileId == -1) + { + /* Error condition. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s: Cannot open file\n", FileName); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + else + { + /* Notify remote system to create a file. */ + nValue = _fstat (FileId, &statbuf); + nFileSize = statbuf.st_size; + sprintf (buff, "C0644 %d %s\n", nFileSize, FileName); + if (write (fileno (stdout), buff, strlen (buff)) < 1) + { + error ("Error sending result status."); + close (FileId); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + /* Receive data from the client expecting 0x00. */ + if ((dwBytes = RcpReceive (buff, blen)) == -1) + { + error ("Cannot receive client data."); + close (FileId); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + if (buff[0] != 0) + { + error ("Remote system Failed."); + close (FileId); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + /* Process the contents of the file. */ + nBytesSent = 0; + while (nBytesSent < nFileSize) + { + /* Read the file. */ + nBytesRead = read (FileId, buff, blen); + if (nBytesRead <= 0) + { + /* Error condition. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s: Cannot read source\n", + FileName); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) + < 1) + error ("Error sending result status."); + close (FileId); + Sleep (RCP_ERR_DELAY); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + nBytesSent += nBytesRead; + if (write (fileno (stdout), buff, nBytesRead) < 1) + { + error ("Error sending file."); + close (FileId); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + } + + close (FileId); + + buff[0] = 0; + if (write (fileno (stdout), buff, 1) < 1) + { + error ("Error sending file termination."); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + } + + /* Receive data from the client expecting 0x00. */ + if ((dwBytes = RcpReceive (buff, blen)) == -1) + { + error ("Cannot receive client data."); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + if (buff[0] != 0) + { + error ("Remote system failed."); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + } + + Target2 = NextTarget (hFile, &bDir); + if (Target2 == NULL) + CloseTarget (hFile); + } + + if (bRecursive) + { + /* Recursive sends are closed by sending "E\n". */ + sprintf (buff, "E\n"); + if (write (fileno (stdout), buff, strlen (buff)) < 1) + { + error ("Error sending directory status."); + return; + } + + /* Receive data from the client. */ + if ((dwBytes = RcpReceive (buff, blen)) == -1) + { + error ("Cannot receive client data."); + return; + } + if (buff[0] != 0) + { + error ("Remote system Failed."); + return; + } + + } + +} + +/* Process files being sent by a remote system. + TARGET is the target specified in the rcp request. + BRECURSIVE specifies if this request recurses sub-directories + on the remote system. Directories may need to be created. + BTARGDIR specifies if the target specified MUST be a directory. + + Assumptions: + All files are written as BINARY to preserve the file size and + data contained in the files. */ +void +RcpSvrRecv (char *Target, BOOL bRecursive, BOOL bTargDir) +{ + char buff[RCP_BUFFER_SIZE + 1]; + int blen = RCP_BUFFER_SIZE; + int FileId; + DWORD dwFileSize; + DWORD dwBytesRecv; + int dwBytes; + int nValue; + BOOL bMoreFiles; + HANDLE hFile = INVALID_HANDLE_VALUE; + char expTarget[MAX_PATH]; + char *Target2; + char *NewLine; + BOOL bDir; + BOOL bTarget; + BOOL bProcessing; + + debug ("RcpSvrRecv\n"); + + strcpy (expTarget, Target); + bDir = bTargDir; + bMoreFiles = ParseTarget (&hFile, expTarget, &bDir); + if (bMoreFiles) + { + Target2 = NextTarget (hFile, &bTarget); + if (Target2 != NULL) + { + /* Error condition: more than one target. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: ambiguous target\n"); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + { + error ("Error sending result status."); + } + Sleep (RCP_ERR_DELAY); + CloseTarget (hFile); + return; + } + } + CloseTarget (hFile); + bTarget = bDir; + + if (bTargDir & !bDir) + { + /* Error condition: Directory required but file specified. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s: Not a directory\n", expTarget); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + { + error ("Error sending result status."); + } + Sleep (RCP_ERR_DELAY); + return; + } + + if (access (expTarget, 02) != 0) + { + if (bDir || (!bDir && (errno != ENOENT))) + { + /* Error condition: Can't access the target. */ + buff[0] = 1; + if (bDir && (errno == ENOENT)) + sprintf (&buff[1], "rcp: %s: No such file or directory\n", + expTarget); + else + sprintf (&buff[1], "rcp: %s: Permission Denied\n", expTarget); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + return; + } + } + + bProcessing = TRUE; + Target2 = expTarget; + + /* Process files/directories from the remote system. */ + while (bProcessing) + { + debug ("Sending null byte ...\n"); + buff[0] = 0; + if (write (fileno (stdout), buff, 1) < 1) + { + error ("Error sending result status."); + return; + } + debug ("Sent.\n"); + + if (bDir) + { + nValue = chdir (Target2); + if (nValue == -1) + { + /* Error condition. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s: No such file or directory\n", + expTarget); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + return; + } + } + + debug ("waiting for data.\n"); + + /* Receive data from the client + File/dir specification ends in a '\n', so read byte by byte + until one is reached or a '\0' is received. */ + if ((dwBytes = RcpReceive (buff, blen)) == -1) + { + error ("Cannot receive client data.");; + return; + } + + debug ("got %d bytes.\n", dwBytes); + debug ("got: %d (%c)\n", buff[0], buff[0]); + + /* Process the file or directory specification. */ + switch (buff[0]) + { + case 0: + case 1: + /* Finished processing. */ + return; + + case 'E': + /* Finished with current directory. Backup to the + parent directory. */ + + Target2 = ".."; + bDir = TRUE; + continue; + + case 'T': + /* This is permissions data related to the -p option. + Just ignore it. */ + continue; + + case 'D': + /* A directory is being identified. */ + + bDir = TRUE; + Target2 = strtok (buff, " "); + Target2 = strtok (NULL, " "); + Target2 = strtok (NULL, " "); + NewLine = strchr (Target2, 0x0a); + *NewLine = 0; + strcpy (expTarget, Target2); + Target2 = expTarget; + + if (access (Target2, 02) != 0) + { + if (errno != ENOENT) + { + /* Error condition: Can't access directory. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s: Directory access failure %d\n", + expTarget, errno); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < + 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + return; + } + /* Create directory. */ + nValue = mkdir (Target2); + if (nValue == -1) + { + /* Error condition: Can't create directory. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s: Directory creation failed\n", + expTarget); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + return; + } + } + continue; + + case 'C': + /* A file is being identified. */ + if (bTarget) + { + Target2 = strtok (buff, " "); + Target2 = strtok (NULL, " "); + Target2 = strtok (NULL, " "); + NewLine = strchr (Target2, 0x0a); + *NewLine = 0; + strcpy (expTarget, Target2); + Target2 = expTarget; + } + + bDir = FALSE; + /* Open the file for writing. */ + FileId = + _open (Target2, _O_WRONLY | _O_TRUNC | _O_CREAT | _O_BINARY, + _S_IWRITE); + if (FileId == -1) + { + /* Error condition. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s :Cannot open file\n", Target2); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + return; + } + break; + + default: + return; + } + + dwFileSize = atol (&buff[6]); + if (debugFlag) + fprintf (stderr, "Receiving file %s of size %lu.\n", Target2, dwFileSize); + + buff[0] = 0; + if (write (fileno (stdout), buff, 1) < 1) + { + error ("Error sending result status."); + close (FileId); + return; + } + + /* Process the file being transferred. */ + dwBytesRecv = 0; + /* If file size=0, expect 1 byte 0x00. */ + if (dwFileSize == 0) + { + if ((dwBytes = RcpReceive (buff, blen)) == -1) + { + error ("Cannot receive client data."); + close (FileId); + return; + } + else if (buff[0] != 0) + error ("Received data for zero length file"); + } + else + { + while (dwBytesRecv < dwFileSize) + { + /* Receive data from the client. */ + if ((dwBytes = read (fileno (stdin), buff, blen)) == -1) + { + error ("Cannot receive client data."); + close (FileId); + return; + } + + dwBytesRecv += dwBytes; + + /* Write the data to the file. */ + nValue = write (FileId, buff, dwBytes); + + if (nValue != dwBytes) + { + /* Error condition: write failure. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s :Cannot write to file\n", + Target2); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error writing error status."); + Sleep (RCP_ERR_DELAY); + close (FileId); + return; + } + } + } + + close (FileId); + } + + return; +} + +/* Determines what type of rcp is being + requested and processes it accordingly. + + Valid rcp requests are in the form: + rcp -t [-d] [-r] [-p] target + rcp -f [r] [-p] target + + NOTE: The -p option is being ignored since there is not a good + correlation between UNIX and NT when it comes to file + permissions and ownership. */ +int +rcp_main (int argc, char **argv) +{ + int i; + char *HomeDir; + + BOOL bTargDir = FALSE; + BOOL bSvrRecv = FALSE; + BOOL bSvrSend = FALSE; + BOOL bRecursive = FALSE; + + /* Get the current working directory. */ + HomeDir = getcwd (NULL, MAX_PATH); + + i = 1; + for (; argv[i] && argv[i][0] == '-'; i++) + { + switch (argv[i][1]) + { + case 'd': + /* Target must be directory. */ + bTargDir = TRUE; + break; + + case 't': + /* rcp is receiving files. */ + bSvrRecv = TRUE; + break; + + case 'f': + /* rcp is sending files. */ + bSvrSend = TRUE; + break; + + case 'p': + /* Preserve Permissions. This option is ignored for now. */ + break; + + case 'r': + /* Recursive send/recv. */ + bRecursive = TRUE; + break; + + default: + fprintf (stderr, "wrong args\n"); + exit (1); + } + } + + if (!bSvrRecv && !bSvrSend) + { + error ("Invalid args"); + exit (1); + } + + if (bSvrRecv) + { + if (bRecursive) + bTargDir = TRUE; + + RcpSvrRecv (argv[i], bRecursive, bTargDir); + } + else + RcpSvrSend (argv[i], bRecursive); + + /* Make sure we end up where we started. */ + chdir (HomeDir); + free (HomeDir); + return 0; +} + +int +main (int argc, char **argv) +{ + return rcp_main (argc, argv); +} Property changes on: trunk/cegcc/tools/rcp/rcp.c ___________________________________________________________________ Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-09-02 23:06:05
|
Revision: 1053 http://cegcc.svn.sourceforge.net/cegcc/?rev=1053&view=rev Author: pedroalves Date: 2007-09-02 16:05:55 -0700 (Sun, 02 Sep 2007) Log Message: ----------- Initial import. * README, ChangeLog, Makefile, rcp.c, config.h, extern.h, util.c: New files. Added Paths: ----------- trunk/cegcc/tools/rcp2/ trunk/cegcc/tools/rcp2/ChangeLog trunk/cegcc/tools/rcp2/Makefile trunk/cegcc/tools/rcp2/README trunk/cegcc/tools/rcp2/config.h trunk/cegcc/tools/rcp2/extern.h trunk/cegcc/tools/rcp2/rcp.c trunk/cegcc/tools/rcp2/util.c Added: trunk/cegcc/tools/rcp2/ChangeLog =================================================================== --- trunk/cegcc/tools/rcp2/ChangeLog (rev 0) +++ trunk/cegcc/tools/rcp2/ChangeLog 2007-09-02 23:05:55 UTC (rev 1053) @@ -0,0 +1,14 @@ +2007-09-03 Pedro Alves <ped...@po...> + + Initial import. + + * README, ChangeLog, Makefile, rcp.c, config.h, extern.h, util.c: + New files. + + +Local Variables: +mode: change-log +left-margin: 8 +fill-column: 74 +version-control: never +End: Property changes on: trunk/cegcc/tools/rcp2/ChangeLog ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp2/Makefile =================================================================== --- trunk/cegcc/tools/rcp2/Makefile (rev 0) +++ trunk/cegcc/tools/rcp2/Makefile 2007-09-02 23:05:55 UTC (rev 1053) @@ -0,0 +1,74 @@ +TARGET=arm-wince-mingw32ce +CFLAGS=-O0 -g3 +WARNFLAGS=-Wall -Wextra + +INCLUDES=-I../errno -I../libcwd -I. +LDFLAGS=-L../errno -L../libcwd +LIBS=-lcwd -lerrno -lws2 + +ALLFLAGS=$(CFLAGS) $(INCLUDES) $(WARNFLAGS) + +CC=$(TARGET)-gcc +STRIP=$(TARGET)-strip + +BINS = rcp_unstripped.exe +STRIPPED_BINS = rcp.exe + +TARGETS = $(STRIPPED_BINS) + +srcdir=. +distdir=rcp-0.2.0 +TAR = tar +TARFLAGS = z +TARFILEEXT = .tar.gz + +SRCDIST_FILES=\ + rcp.c Makefile README TODO COPYING ChangeLog + +BINDIST_FILES=\ + rcp.exe + +OBJECTS=rcp.o util.o + +all: $(TARGETS) +bins: $(BINS) + +.c.o: + $(CC) -o $@ $< -c $(ALLFLAGS) + +rcp_unstripped.exe: $(OBJECTS) Makefile + $(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(ALLFLAGS) $(LIBS) + +rcp.exe: rcp_unstripped.exe + $(STRIP) $< -o $@ + +download: rcp.exe + pcp rcp.exe ":/rcp.exe" + +clean: + rm -f $(BINS) $(STRIPPED_BINS) $(OBJECTS) + +dist: srcdist bindist + +srcdist: all + rm -rf $(distdir) + mkdir $(distdir) + chmod 755 $(distdir) + for i in $(SRCDIST_FILES); do \ + cp -p $(srcdir)/$$i $(distdir)/$$i ; \ + done + rm -f $(distdir).tar.gz + $(TAR) $(TARFLAGS)cf $(distdir)-src$(TARFILEEXT) $(distdir) + +bindist: all + rm -rf $(distdir) + mkdir $(distdir) + chmod 755 $(distdir) + for i in $(BINDIST_FILES); do \ + cp -p $(srcdir)/$$i $(distdir)/$$i ; \ + done + rm -f $(distdir).tar.gz + $(TAR) $(TARFLAGS)cf $(distdir)-bin$(TARFILEEXT) $(distdir) + + +.PHONY: all install download clean dist bindist srcdist Property changes on: trunk/cegcc/tools/rcp2/Makefile ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp2/README =================================================================== --- trunk/cegcc/tools/rcp2/README (rev 0) +++ trunk/cegcc/tools/rcp2/README 2007-09-02 23:05:55 UTC (rev 1053) @@ -0,0 +1,16 @@ + README for rcp for Windows CE + +This directory contains rcp for Windows CE. + +To build make sure you have the mingw32ce toolchain on your path, and +type make. + +Have fun! + +Pedro Alves + +-- + +REPORTING BUGS: +ce...@so... +pe...@po... Property changes on: trunk/cegcc/tools/rcp2/README ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp2/config.h =================================================================== --- trunk/cegcc/tools/rcp2/config.h (rev 0) +++ trunk/cegcc/tools/rcp2/config.h 2007-09-02 23:05:55 UTC (rev 1053) @@ -0,0 +1,10 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define RCP_NOPERMS 1 + +#define PACKAGE_NAME "rcp (Windows CE)" +#define PACKAGE_VERSION "1.0" +#define PACKAGE_BUGREPORT "ce...@li..." + +#endif Property changes on: trunk/cegcc/tools/rcp2/config.h ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp2/extern.h =================================================================== --- trunk/cegcc/tools/rcp2/extern.h (rev 0) +++ trunk/cegcc/tools/rcp2/extern.h 2007-09-02 23:05:55 UTC (rev 1053) @@ -0,0 +1,84 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.1 (Berkeley) 5/31/93 + */ + +typedef struct { + int cnt; + char *buf; +} BUF; + +extern int iamremote; + +BUF *allocbuf (BUF *, int, int); +char *colon (char *); +void lostconn (int); +void nospace (void); +int okname (char *); +void run_err (const char *, ...); +int susystem (char *, int); +void verifydir (char *); + +/* Print the program name and error message MESSAGE, which is a + printf-style format string with optional args. If ERRNUM is + nonzero, print its corresponding system error message. Exit with + status STATUS if it is nonzero. */ +void error (int status, int errnum, const char *message, ...); + +struct rcp_stat +{ + _dev_t st_dev; /* Equivalent to drive number 0=A 1=B ... */ + _ino_t st_ino; /* Always zero ? */ + _mode_t st_mode; /* See above constants */ + short st_nlink; /* Number of links. */ + short st_uid; /* User: Maybe significant on NT ? */ + short st_gid; /* Group: Ditto */ + _dev_t st_rdev; /* Seems useless (not even filled in) */ + _off_t st_size; /* File size in bytes */ + time_t st_atime; /* Accessed date (always 00:00 hrs local + * on FAT) */ + time_t st_mtime; /* Modified time */ + time_t st_ctime; /* Creation time */ +}; + +#include <cwd.h> +#include <dirent.h> + +int rcp_open (const char *path, int flag, int mode); +int rcp_mkdir (const char *path); +int rcp_stat (const char *path, struct rcp_stat *statbuf); +int rcp_fstat (int fd, struct rcp_stat *statbuf); +DIR * rcp_opendir (const char *path); + + +#define open rcp_open +#define mkdir rcp_mkdir +#define stat rcp_stat +#define fstat rcp_fstat +#define opendir rcp_opendir Property changes on: trunk/cegcc/tools/rcp2/extern.h ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp2/rcp.c =================================================================== --- trunk/cegcc/tools/rcp2/rcp.c (rev 0) +++ trunk/cegcc/tools/rcp2/rcp.c 2007-09-02 23:05:55 UTC (rev 1053) @@ -0,0 +1,974 @@ +/* + * Copyright (c) 1983, 1990, 1992, 1993, 2002 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <winsock2.h> +#include <windows.h> +#include <ctype.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <string.h> +#include <unistd.h> +#include <getopt.h> +#include <utime.h> + +#include "extern.h" + +#define OPTIONS "dfprtV" + +static const char *short_options = OPTIONS; +static struct option long_options[] = +{ + { "recursive", required_argument, 0, 'r' }, + { "preserve", no_argument, 0, 'p' }, + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'V' }, + /* Server option. */ + { "directory", required_argument, 0, 'd' }, + { "from", required_argument, 0, 'f' }, + { "to", required_argument, 0, 't' }, + { 0, 0, 0, 0 } +}; + +typedef unsigned short u_short; + +struct passwd *pwd; +u_short port; +int errs; +int pflag, iamremote, iamrecursive, targetshouldbedirectory; + +#define CMDNEEDS 64 +char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ + +int response (void); +void rsource (char *, struct stat *); +void sink (int, char *[]); +void source (int, char *[]); +void tolocal (int, char *[]); +void toremote (char *, int, char *[]); +void usage (void); +void help (void); + +char *program_name; + +/* Print the program name and error message MESSAGE, which is a + printf-style format string with optional args. If ERRNUM is + nonzero, print its corresponding system error message. Exit with + status STATUS if it is nonzero. */ +void +error (int status, int errnum, const char *message, ...) +{ + va_list args; + + fflush (stdout); + fprintf (stderr, "%s: ", program_name); + + va_start (args, message); + vfprintf (stderr, message, args); + va_end (args); + + if (errnum) + { + char const *s = strerror (errnum); + if (!s) + s = "Unknown system error"; + + fprintf (stderr, ": %s", s); + } + putc ('\n', stderr); + fflush (stderr); + if (status) + exit (status); +} + +//#define WAIT_DEBUGGER + +#ifdef WAIT_DEBUGGER +volatile int cont = 0; +#endif + +int +main (int argc, char *argv[]) +{ +#ifdef WAIT_DEBUGGER + /* useful to attach a debugger. */ + while (!cont) + Sleep (100); /* put a break here, and then 'p cont = 1' */ + if (cont < 0) + return 0; +#endif + + struct servent *sp; + int ch, fflag, tflag; + char *targ; + const char *shell; + + program_name = argv[0]; + + fflag = tflag = 0; + while ((ch = getopt_long (argc, argv, short_options, long_options, 0)) + != EOF) + switch(ch) + { /* User-visible flags. */ + case 'K': + break; + + case 'p': + pflag = 1; + break; + + case 'r': + iamrecursive = 1; + break; + + /* Server options. */ + case 'd': + targetshouldbedirectory = 1; + break; + + case 'f': /* "from" */ + iamremote = 1; + fflag = 1; + break; + + case 't': /* "to" */ + iamremote = 1; + tflag = 1; + break; + + case 'V': + printf ("rcp (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); + exit (0); + break; + + case 'h': + help (); + break; + + case '?': + default: + usage (); + } + argc -= optind; + argv += optind; +#if 0 + sp = getservbyname (shell = "shell", "tcp"); + if (sp == NULL) + error (1, 0, "%s/tcp: unknown service", shell); + port = sp->s_port; +#endif + + if (fflag) + { /* Follow "protocol", send data. */ + response (); + source (argc, argv); + exit (errs); + } + + if (tflag) + { /* Receive data. */ + sink (argc, argv); + exit (errs); + } + + if (argc < 2) + usage (); + if (argc > 2) + targetshouldbedirectory = 1; + + /* Command to be executed on remote system using "rsh". */ + snprintf (cmd, sizeof cmd, "rcp%s%s%s", + iamrecursive ? " -r" : "", pflag ? " -p" : "", + targetshouldbedirectory ? " -d" : ""); + + targ = colon (argv[argc - 1]); /* Dest is remote host. */ + if (targ) /* Dest is remote host. */ + toremote (targ, argc, argv); + else + { + tolocal (argc, argv); /* Dest is local host. */ + if (targetshouldbedirectory) + verifydir(argv[argc - 1]); + } + exit (errs); +} + +void +toremote (char *targ, int argc, char *argv[]) +{ + int i; + // int len, tos; + char *src, *tuser, *thost; + + // char *bp, *host, *suser, ; + + *targ++ = 0; + if (*targ == 0) + targ = "."; + + thost = strchr (argv[argc - 1], '@'); + if (thost) + { + /* user@host */ + *thost++ = 0; + tuser = argv[argc - 1]; + if (*tuser == '\0') + tuser = NULL; + else if (!okname(tuser)) + exit (1); + } + else + { + thost = argv[argc - 1]; + tuser = NULL; + } + + for (i = 0; i < argc - 1; i++) + { + src = colon (argv[i]); + if (src) + { /* remote to remote */ +#if 0 +/* Currently unsupported. */ + *src++ = 0; + if (*src == 0) + src = "."; + host = strchr (argv[i], '@'); + len = strlen (PATH_RSH) + strlen (argv[i]) + + strlen (src) + (tuser ? strlen (tuser) : 0) + + strlen (thost) + strlen (targ) + CMDNEEDS + 20; + if (!(bp = malloc (len))) + err (1, NULL); + if (host) + { + *host++ = 0; + suser = argv[i]; + if (*suser == '\0') + suser = pwd->pw_name; + else if (!okname (suser)) + continue; + snprintf (bp, len, + "%s %s -l %s -n %s %s '%s%s%s:%s'", + PATH_RSH, host, suser, cmd, src, + tuser ? tuser : "", tuser ? "@" : "", + thost, targ); + } + else + snprintf (bp, len, + "exec %s %s -n %s %s '%s%s%s:%s'", + PATH_RSH, argv[i], cmd, src, + tuser ? tuser : "", tuser ? "@" : "", + thost, targ); + susystem (bp, userid); + free (bp); +#endif + } + else + { /* local to remote */ +#if 0 + if (rem == -1) + { + len = strlen (targ) + CMDNEEDS + 20; + if (!(bp = malloc (len))) + err (1, NULL); + snprintf (bp, len, "%s -t %s", cmd, targ); + host = thost; + rem = rcmd (&host, port, pwd->pw_name, + tuser ? tuser : pwd->pw_name, bp, 0); + if (rem < 0) + exit (1); +#if defined (IP_TOS) && defined (IPPROTO_IP) && defined (IPTOS_THROUGHPUT) + tos = IPTOS_THROUGHPUT; + if (setsockopt (rem, IPPROTO_IP, IP_TOS, + (char *) &tos, sizeof(int)) < 0) + error (0, errno, "TOS (ignored)"); +#endif + if (response () < 0) + exit(1); + free(bp); + setuid(userid); + } +#endif + source(1, argv+i); + } + } +} + +void +tolocal (int argc, char *argv[]) +{ +#if 0 + + int i, len, tos; + char *bp, *host, *src, *suser; + + for (i = 0; i < argc - 1; i++) + { + if (!(src = colon (argv[i]))) + { /* Local to local. */ + len = strlen (PATH_CP) + strlen (argv[i]) + + strlen (argv[argc - 1]) + 20; + if (!(bp = malloc (len))) + err (1, NULL); + snprintf (bp, len, "exec %s%s%s %s %s", PATH_CP, + iamrecursive ? " -r" : "", pflag ? " -p" : "", + argv[i], argv[argc - 1]); + if (susystem (bp, userid)) + ++errs; + free (bp); + continue; + } + *src++ = 0; + if (*src == 0) + src = "."; + if ((host = strchr(argv[i], '@')) == NULL) + { + host = argv[i]; + suser = pwd->pw_name; + } + else + { + *host++ = 0; + suser = argv[i]; + if (*suser == '\0') + suser = pwd->pw_name; + else if (!okname (suser)) + continue; + } + len = strlen (src) + CMDNEEDS + 20; + if ((bp = malloc (len)) == NULL) + err (1, NULL); + snprintf (bp, len, "%s -f %s", cmd, src); + rem = + rcmd (&host, port, pwd->pw_name, suser, bp, 0); + free (bp); + if (rem < 0) + { + ++errs; + continue; + } + seteuid (userid); +#if defined (IP_TOS) && defined (IPPROTO_IP) && defined (IPTOS_THROUGHPUT) + tos = IPTOS_THROUGHPUT; + if (setsockopt (rem, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof (int)) < 0) + error (0, errno, "TOS (ignored)"); +#endif + sink (1, argv + argc - 1); + seteuid (0); + close (rem); + rem = -1; + } +#endif +} + +static int +write_stat_time (int fd, struct stat *stat) +{ + char buf[4 * sizeof (long) * 3 + 2]; + time_t a_sec, m_sec; + long a_usec = 0, m_usec = 0; + + a_sec = stat->st_atime; + m_sec = stat->st_mtime; + + snprintf (buf, sizeof(buf), "T%ld %ld %ld %ld\n", + m_sec, m_usec, a_sec, a_usec); + return write (fd, buf, strlen (buf)); +} + +void +source (int argc, char *argv[]) +{ + struct stat stb; + static BUF buffer; + BUF *bp; + off_t i; + int amt, fd, haderr, indx, result; + char *last, *name, buf[BUFSIZ]; + + for (indx = 0; indx < argc; ++indx) + { + name = argv[indx]; +#ifndef _WIN32 + if ((fd = open (name, O_RDONLY, 0)) == -1) + goto syserr; + if (fstat (fd, &stb)) +#else + fd = -1; + if (stat (name, &stb)) +#endif + { + syserr: + run_err ("%s: %s", name, strerror (errno)); + goto next; + } + switch (stb.st_mode & S_IFMT) + { + case S_IFREG: +#ifdef _WIN32 + if ((fd = open (name, O_RDONLY, 0)) == -1) + goto syserr; +#endif + break; + + case S_IFDIR: + if (iamrecursive) + { + rsource (name, &stb); + goto next; + } + /* FALLTHROUGH */ + default: + run_err ("%s: not a regular file", name); + goto next; + } + if ((last = strrchr (name, '/')) == NULL + && (last = strrchr (name, '\\')) == NULL) + last = name; + else + ++last; + if (pflag) + { + write_stat_time (STDOUT_FILENO, &stb); + if (response() < 0) + goto next; + } +#define RCP_MODEMASK (S_IRWXU) + snprintf(buf, sizeof buf, + (sizeof(stb.st_size) > sizeof(long) + ? "C%04o %qd %s\n" + : "C%04o %ld %s\n"), + stb.st_mode & RCP_MODEMASK, stb.st_size, last); + write (STDOUT_FILENO, buf, strlen (buf)); + if (response () < 0) + goto next; + if ((bp = allocbuf (&buffer, fd, BUFSIZ)) == NULL) + { + next: + close (fd); + continue; + } + + /* Keep writing after an error so that we stay sync'd up. */ + for (haderr = i = 0; i < stb.st_size; i += bp->cnt) + { + amt = bp->cnt; + if (i + amt > stb.st_size) + amt = stb.st_size - i; + if (!haderr) + { + result = read (fd, bp->buf, amt); + if (result != amt) + haderr = result >= 0 ? EIO : errno; + } + if (haderr) + write (STDOUT_FILENO, bp->buf, amt); + else + { + result = write (STDOUT_FILENO, bp->buf, amt); + if (result != amt) + haderr = result >= 0 ? EIO : errno; + } + } + if (close (fd) && !haderr) + haderr = errno; + if (!haderr) + write (STDOUT_FILENO, "", 1); + else + run_err ("%s: %s", name, strerror(haderr)); + response (); + } +} + +void +rsource (char *name, struct stat *statp) +{ + DIR *dirp; + struct dirent *dp; + char *last, *vect[1]; + char *buf; + int buf_len; + + if (!(dirp = opendir (name))) + { + run_err ("%s: %s", name, strerror(errno)); + return; + } + last = strrchr (name, '/'); + if (last == 0) + last = strrchr (name, '\\'); + if (last == 0) + last = name; + else + last++; + + if (pflag) + { + write_stat_time (STDOUT_FILENO, statp); + if (response () < 0) { + closedir (dirp); + return; + } + } + + buf_len = + 1 + sizeof (int) * 3 + 1 + sizeof (int) * 3 + 1 + strlen (last) + 2; + buf = malloc (buf_len); + if (! buf) + { + run_err ("malloc failed for %d bytes", buf_len); + closedir (dirp); + return; + } + + sprintf (buf, "D%04o %d %s\n", statp->st_mode & RCP_MODEMASK, 0, last); + write (STDOUT_FILENO, buf, strlen (buf)); + free (buf); + + if (response () < 0) + { + closedir (dirp); + return; + } + + while ((dp = readdir(dirp))) + { + if (!strcmp (dp->d_name, ".") || !strcmp (dp->d_name, "..")) + continue; + + buf_len = strlen (name) + 1 + strlen (dp->d_name) + 1; + buf = malloc (buf_len); + if (! buf) + { + run_err ("malloc_failed for %d bytes", buf_len); + continue; + } + + sprintf (buf, "%s/%s", name, dp->d_name); + vect[0] = buf; + source(1, vect); + free (buf); + } + + closedir (dirp); + write (STDOUT_FILENO, "E\n", 2); + response (); +} + +void +sink (int argc, char *argv[]) +{ + static BUF buffer; + struct stat stb; + struct timeval tv[2]; + enum { YES, NO, DISPLAYED } wrerr; + BUF *bp; + off_t i, j; + int amt, count, exists, first, mode, ofd, omode; + int setimes, size, targisdir, wrerrno; + char ch, *cp, *np, *targ, *vect[1], buf[BUFSIZ]; + const char *why; + +#define atime tv[0] +#define mtime tv[1] +#define SCREWUP(str) { why = str; goto screwup; } + + setimes = targisdir = 0; + if (argc != 1) + { + run_err ("ambiguous target"); + exit (1); + } + targ = *argv; + if (targetshouldbedirectory) + verifydir (targ); + if (write (STDOUT_FILENO, "", 1) != 1) + return; + if (stat (targ, &stb) == 0 && S_ISDIR (stb.st_mode)) + targisdir = 1; + for (first = 1;; first = 0) + { + cp = buf; + if (read (STDIN_FILENO, cp, 1) <= 0) + return; + if (*cp++ == '\n') + SCREWUP ("unexpected <newline>"); + do + { + if (read (STDIN_FILENO, &ch, sizeof ch) != sizeof ch) + SCREWUP("lost connection"); + *cp++ = ch; + } while (cp < &buf[BUFSIZ - 1] && ch != '\n'); + *cp = 0; + + if (buf[0] == '\01' || buf[0] == '\02') + { + if (iamremote == 0) + write (STDERR_FILENO, buf + 1, strlen(buf + 1)); + if (buf[0] == '\02') + exit (1); + ++errs; + continue; + } + if (buf[0] == 'E') + { + write (STDOUT_FILENO, "", 1); + return; + } + + if (ch == '\n') + *--cp = 0; + +#define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0'); + cp = buf; + if (*cp == 'T') + { + setimes++; + cp++; + getnum(mtime.tv_sec); + if (*cp++ != ' ') + SCREWUP ("mtime.sec not delimited"); + getnum (mtime.tv_usec); + if (*cp++ != ' ') + SCREWUP ("mtime.usec not delimited"); + getnum (atime.tv_sec); + if (*cp++ != ' ') + SCREWUP ("atime.sec not delimited"); + getnum (atime.tv_usec); + if (*cp++ != '\0') + SCREWUP ("atime.usec not delimited"); + write (STDOUT_FILENO, "", 1); + continue; + } + if (*cp != 'C' && *cp != 'D') + { + /* + * Check for the case "rcp remote:foo\* local:bar". + * In this case, the line "No match." can be returned + * by the shell before the rcp command on the remote is + * executed so the ^Aerror_message convention isn't + * followed. + */ + if (first) + { + run_err ("%s", cp); + exit (1); + } + SCREWUP ("expected control record"); + } + mode = 0; + for (++cp; cp < buf + 5; cp++) + { + if (*cp < '0' || *cp > '7') + SCREWUP ("bad mode"); + mode = (mode << 3) | (*cp - '0'); + } + if (*cp++ != ' ') + SCREWUP ("mode not delimited"); + + for (size = 0; isdigit(*cp);) + size = size * 10 + (*cp++ - '0'); + if (*cp++ != ' ') + SCREWUP ("size not delimited"); + if (targisdir) + { + static char *namebuf; + static int cursize; + size_t need; + + need = strlen (targ) + strlen (cp) + 250; + if (need > cursize) + { + if (!(namebuf = malloc (need))) + run_err("%s", strerror (errno)); + } + snprintf (namebuf, need, "%s%s%s", targ, *targ ? "/" : "", cp); + np = namebuf; + } + else + np = targ; + exists = stat (np, &stb) == 0; + if (buf[0] == 'D') + { + int mod_flag = pflag; + if (exists) + { + if (!S_ISDIR (stb.st_mode)) + { + __set_errno (ENOTDIR); + goto bad; + } + if (pflag) + chmod (np, mode); + } + else + { + /* Handle copying from a read-only directory */ + mod_flag = 1; + if (mkdir (np) < 0) + goto bad; + } + vect[0] = np; + sink (1, vect); + if (setimes) + { + struct utimbuf utbuf; + utbuf.actime = atime.tv_sec; + utbuf.modtime = mtime.tv_sec; + setimes = 0; + if (utime (np, &utbuf) < 0) + run_err ("%s: set times: %s", np, strerror (errno)); + } + if (mod_flag) + chmod (np, mode); + continue; + } + omode = mode; + mode |= S_IWRITE; + if ((ofd = open (np, O_WRONLY|O_CREAT, mode)) == -1) + { + bad: + run_err ("%s: %s", np, strerror(errno)); + continue; + } + write (STDOUT_FILENO, "", 1); + if ((bp = allocbuf (&buffer, ofd, BUFSIZ)) == NULL) + { + close (ofd); + continue; + } + cp = bp->buf; + wrerr = NO; + for (count = i = 0; i < size; i += BUFSIZ) + { + amt = BUFSIZ; + if (i + amt > size) + amt = size - i; + count += amt; + do + { + j = read (STDIN_FILENO, cp, amt); + if (j <= 0) + { + run_err ("%s", j ? strerror(errno) : "dropped connection"); + exit (1); + } + amt -= j; + cp += j; + } while (amt > 0); + if (count == bp->cnt) + { + /* Keep reading so we stay sync'd up. */ + if (wrerr == NO) + { + j = write (ofd, bp->buf, count); + if (j != count) + { + wrerr = YES; + wrerrno = j >= 0 ? EIO : errno; + } + } + count = 0; + cp = bp->buf; + } + } + if (count != 0 && wrerr == NO + && (j = write (ofd, bp->buf, count)) != count) + { + wrerr = YES; + wrerrno = j >= 0 ? EIO : errno; + } + if (ftruncate (ofd, size)) + { + run_err ("%s: truncate: %s", np, strerror (errno)); + wrerr = DISPLAYED; + } + if (pflag) + { + if (exists || omode != mode) + if (chmod (np, omode)) + run_err ("%s: set mode: %s", np, strerror (errno)); + } + else + { + if (!exists && omode != mode) + if (chmod (np, omode)) + run_err ("%s: set mode: %s", np, strerror (errno)); + } + close (ofd); + response (); + if (setimes && wrerr == NO) + { + struct utimbuf utbuf; + utbuf.actime = atime.tv_sec; + utbuf.modtime = mtime.tv_sec; + setimes = 0; + if (utime (np, &utbuf) < 0) + { + run_err ("%s: set times: %s", np, strerror (errno)); + wrerr = DISPLAYED; + } + } + switch (wrerr) + { + case YES: + run_err ("%s: %s", np, strerror(wrerrno)); + break; + + case NO: + write (STDOUT_FILENO, "", 1); + break; + + case DISPLAYED: + break; + } + } +screwup: + run_err ("protocol error: %s", why); + exit (1); +} + +int +response () +{ + char ch, *cp, resp, rbuf[BUFSIZ]; + + if (read (STDIN_FILENO, &resp, sizeof resp) != sizeof resp) + lostconn (0); + + cp = rbuf; + switch (resp) + { + case 0: /* ok */ + return 0; + + default: + *cp++ = resp; + /* FALLTHROUGH */ + case 1: /* error, followed by error msg */ + case 2: /* fatal error, "" */ + do + { + if (read (STDIN_FILENO, &ch, sizeof(ch)) != sizeof(ch)) + lostconn(0); + *cp++ = ch; + } while (cp < &rbuf[BUFSIZ] && ch != '\n'); + + if (!iamremote) + write (STDERR_FILENO, rbuf, cp - rbuf); + ++errs; + if (resp == 1) + return -1; + exit (1); + } + /* NOTREACHED */ +} + +void +usage () +{ + fprintf (stderr, + "usage: rcp [-p] f1 f2; or: rcp [-pr] f1 ... fn directory\n"); + exit (1); +} + +void +help () +{ + puts ("rcp - remote file copy."); + puts ("usage: rcp [-p] f1 f2; or: rcp [-pr] f1 ... fn directory\n"); + puts ("\ + -p, --preserve attempt to preserve (duplicate) in its copies the\n\ + modification times and modes of the source files"); + puts ("\ + -r, --recursive If any of the source files are directories, copies\n\ + each subtree rooted at that name; in this case the\n\ + destination must be a directory"); + + puts ("\ + --help give this help list"); + puts ("\ + -V, --version print program version"); + fprintf (stdout, "\nSubmit bug reports to %s.\n", PACKAGE_BUGREPORT); + exit (0); +} + +#include <stdarg.h> + +void +warnerr(int doerrno, const char *fmt, va_list ap) +{ + int sverrno = errno; + fprintf(stderr, "rcp"); + if(fmt != NULL || doerrno) + fprintf(stderr, ": "); + if (fmt != NULL){ + vfprintf(stderr, fmt, ap); + if(doerrno) + fprintf(stderr, ": "); + } + if(doerrno) + fprintf(stderr, "%s", strerror(sverrno)); + fprintf(stderr, "\n"); +} + +void +vwarnx(const char *fmt, va_list ap) +{ + warnerr(0, fmt, ap); +} + +void +run_err (const char *fmt, ...) +{ + static FILE *fp; + va_list ap; + va_start (ap, fmt); + ++errs; + if (fp == NULL && !(fp = fdopen (STDOUT_FILENO, "w"))) + return; + fprintf (fp, "%c", 0x01); + fprintf (fp, "rcp: "); + vfprintf (fp, fmt, ap); + fprintf (fp, "\n"); + fflush (fp); + + if (!iamremote) + vwarnx (fmt, ap); + + va_end (ap); +} Property changes on: trunk/cegcc/tools/rcp2/rcp.c ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp2/util.c =================================================================== --- trunk/cegcc/tools/rcp2/util.c (rev 0) +++ trunk/cegcc/tools/rcp2/util.c 2007-09-02 23:05:55 UTC (rev 1053) @@ -0,0 +1,204 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <sys/param.h> +#include <sys/stat.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <windows.h> + +#include "extern.h" + +char * +colon(char *cp) +{ + if (*cp == ':') /* Leading colon is part of file name. */ + return (0); + + for (; *cp; ++cp) { + if (*cp == ':') + return (cp); + if (*cp == '/') + return (0); + } + return (0); +} + +void +verifydir(char *cp) +{ + struct stat stb; + + if (!stat(cp, &stb)) { + if (S_ISDIR(stb.st_mode)) + return; + __set_errno (ENOTDIR); + } + run_err("%s: %s", cp, strerror(errno)); + exit(1); +} + +int +okname(char *cp0) +{ + int c; + char *cp; + + cp = cp0; + do { + c = *cp; + if (c & 0200) + goto bad; + if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-') + goto bad; + } while (*++cp); + return (1); + +bad: + error (0, 0, "%s: invalid user name", cp0); + return (0); +} + +#if 0 +int +susystem(char *s, int userid) +{ + sig_t istat, qstat; + int status, w; + pid_t pid; + + pid = vfork(); + switch (pid) { + case -1: + return (127); + + case 0: + (void)setuid(userid); + execl(PATH_BSHELL, "sh", "-c", s, NULL); + _exit(127); + } + istat = signal(SIGINT, SIG_IGN); + qstat = signal(SIGQUIT, SIG_IGN); + if (waitpid(pid, &status, 0) < 0) + status = -1; + (void)signal(SIGINT, istat); + (void)signal(SIGQUIT, qstat); + return (status); +} +#endif + +BUF * +allocbuf(BUF *bp, int fd, int blksize) +{ + struct stat stb; + size_t size; + + if (fstat(fd, &stb) < 0) { + run_err("fstat: %s", strerror(errno)); + return (0); + } +#ifndef roundup +# define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#endif + size = roundup(BUFSIZ, blksize); + if (size == 0) + size = blksize; + if (bp->cnt >= size) + return (bp); + if ((bp->buf = realloc(bp->buf, size)) == NULL) { + bp->cnt = 0; + run_err("%s", strerror(errno)); + return (0); + } + bp->cnt = size; + return (bp); +} + +typedef void RETSIGTYPE; + +RETSIGTYPE +lostconn(int signo) +{ + if (!iamremote) + error (0, 0, "lost connection"); + exit(1); +} + + +/* Wince cwd support. */ + +#undef stat +#undef fstat +#undef mkdir +#undef open +#undef opendir + +int +rcp_stat (const char *path, struct rcp_stat *statbuf) +{ + char buf[MAX_PATH]; + libcwd_fixpath (buf, path); + return stat (buf, (struct stat *) statbuf); +} + +int +rcp_fstat (int fd, struct rcp_stat *statbuf) +{ + return fstat (fd, (struct stat *) statbuf); +} + +int +rcp_open (const char *path, int flag, int mode) +{ + char buf[MAX_PATH]; + libcwd_fixpath (buf, path); + return open (buf, flag, mode); +} + +int +rcp_mkdir (const char *path) +{ + char buf[MAX_PATH]; + libcwd_fixpath (buf, path); + return mkdir (buf); +} + +DIR * +rcp_opendir (const char *path) +{ + char buf[MAX_PATH]; + libcwd_fixpath (buf, path); + return opendir (buf); +} Property changes on: trunk/cegcc/tools/rcp2/util.c ___________________________________________________________________ Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-11-18 16:33:16
|
Revision: 1075 http://cegcc.svn.sourceforge.net/cegcc/?rev=1075&view=rev Author: pedroalves Date: 2007-11-18 08:33:11 -0800 (Sun, 18 Nov 2007) Log Message: ----------- Initial release. * Makefile, README, common.h, driver.cpp, makemsvc.sh, msvc.cpp, msvc.h, msvc.obj: New files. Added Paths: ----------- trunk/cegcc/tools/abicheck/ trunk/cegcc/tools/abicheck/ChangeLog trunk/cegcc/tools/abicheck/Makefile trunk/cegcc/tools/abicheck/README trunk/cegcc/tools/abicheck/common.h trunk/cegcc/tools/abicheck/driver.cpp trunk/cegcc/tools/abicheck/makemsvc.sh trunk/cegcc/tools/abicheck/msvc.cpp trunk/cegcc/tools/abicheck/msvc.h trunk/cegcc/tools/abicheck/msvc.obj Added: trunk/cegcc/tools/abicheck/ChangeLog =================================================================== --- trunk/cegcc/tools/abicheck/ChangeLog (rev 0) +++ trunk/cegcc/tools/abicheck/ChangeLog 2007-11-18 16:33:11 UTC (rev 1075) @@ -0,0 +1,5 @@ +2007-11-18 Pedro Alves <ped...@po...> + + Initial release. + * Makefile, README, common.h, driver.cpp, makemsvc.sh, msvc.cpp, + msvc.h, msvc.obj: New files. Property changes on: trunk/cegcc/tools/abicheck/ChangeLog ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/abicheck/Makefile =================================================================== --- trunk/cegcc/tools/abicheck/Makefile (rev 0) +++ trunk/cegcc/tools/abicheck/Makefile 2007-11-18 16:33:11 UTC (rev 1075) @@ -0,0 +1,32 @@ +TARGET=arm-wince-mingw32ce +CXX=$(TARGET)-g++ +STRIP=$(TARGET)-strip +CXXFLAGS=-O3 + +OBJECTS=driver.o + +all: driver_gcc.exe + +msvc: + makemsvc.sh + +all-msvc: msvc all + +msvc.obj: + +.cpp.o: + $(CXX) $< -o $@ $(CXXFLAGS) -c + +driver_gcc_unstripped.exe: $(OBJECTS) msvc.obj + $(CXX) $(OBJECTS) msvc.obj -o $@ $(CXXFLAGS) + +driver_gcc.exe: driver_gcc_unstripped.exe + $(STRIP) $< -o $@ + +clean: + rm -f $(OBJECTS) driver_gcc.exe driver_gcc_unstripped.exe *~ + +clean-msvc: clean + rm -f msvc.obj + +.PHONY: all clean Property changes on: trunk/cegcc/tools/abicheck/Makefile ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/abicheck/README =================================================================== --- trunk/cegcc/tools/abicheck/README (rev 0) +++ trunk/cegcc/tools/abicheck/README 2007-11-18 16:33:11 UTC (rev 1075) @@ -0,0 +1,13 @@ +A simple ABI checker. It isn't very smart, or automatic, but +serves the immediate purpose. + +The idea is to have gcc built code interfacing with MSVC +built code, and ensuring the the arguments are passed +correctly to both sides. + +msvc.obj is built with MSVC. Since access to a MSVC is limited, +the object file is kept in the repository. + +To build, type `make'. If you're changing the msvc.cpp file, be sure +to have access to an MSVC that can output ARM WinCE code, and type +`make all-msvc'. Property changes on: trunk/cegcc/tools/abicheck/README ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/abicheck/common.h =================================================================== --- trunk/cegcc/tools/abicheck/common.h (rev 0) +++ trunk/cegcc/tools/abicheck/common.h 2007-11-18 16:33:11 UTC (rev 1075) @@ -0,0 +1,39 @@ +#ifndef COMMON_H +#define COMMON_H + +#include <windows.h> +struct struct64 +{ + __int64 value; +}; + +struct struct32 +{ + int value; +}; + +struct T1 +{ + unsigned short f1; + int f2; + char f3; + char f4; +}; + +struct T2 +{ + unsigned short f1; + __int64 f2; + char f3; + char f4; +}; + +struct T3 +{ + unsigned short f1; + double f2; + char f3; + char f4; +}; + +#endif Property changes on: trunk/cegcc/tools/abicheck/common.h ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/abicheck/driver.cpp =================================================================== --- trunk/cegcc/tools/abicheck/driver.cpp (rev 0) +++ trunk/cegcc/tools/abicheck/driver.cpp 2007-11-18 16:33:11 UTC (rev 1075) @@ -0,0 +1,37 @@ +#ifdef __GNUC__ +# define _tmain main +# define LL(X) X ## LL +#else +# define LL(X) X ## i64 +#endif + +#include "common.h" +#include "msvc.h" + +struct struct64 dd64 = { LL(0x1122334455667788) }; +struct struct32 dd32 = { 0x11223344 }; + +int +_tmain (void) +{ + print_offsets (); + + test_struct64 ("", dd64); + test_struct32 ("", dd32); + + struct struct64 ldd64 = test_ret_struct64 (); + struct struct32 ldd32 = test_ret_struct32 (); + + long double ldouble = test_ret_ldouble(); + double doubl = test_ret_double(); + + printf("test_ret_ldouble, ldouble = %lf\n", ldouble); + printf("test_ret_double, doubl = %f\n", doubl); + + test_ldouble("", 0.12345678); + test_uint64("", LL(0x1122334455667788)); + + test_odd_regs64(0, LL(0x1111111122222222), + 3, LL(0x4444444455555555), + 6, LL(0x7777777788888888)); +} Property changes on: trunk/cegcc/tools/abicheck/driver.cpp ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/abicheck/makemsvc.sh =================================================================== --- trunk/cegcc/tools/abicheck/makemsvc.sh (rev 0) +++ trunk/cegcc/tools/abicheck/makemsvc.sh 2007-11-18 16:33:11 UTC (rev 1075) @@ -0,0 +1,19 @@ +#!/bin/bash + +MSVC_PATH=d:\\Programas\\Microsoft\ Visual\ Studio\ 8 +PATH=${MSVC_PATH}/Common7/IDE:${PATH} +PATH=${MSVC_PATH}/VC/ce/bin/x86_arm:${PATH} + +export PATH + +INCLUDE="${MSVC_PATH}\\VC\\ce\\include" +INCLUDE="${MSVC_PATH}\\SmartDevices\\SDK\\PocketPC2003\\Include;${INCLUDE}" + +export INCLUDE + +cl.exe /nologo /W3 /O2 \ + /D "ARM" /D "_M_ARM" \ + /D "WIN32" /D "NDEBUG" /D "_WINDOWS" \ + /D "STRICT" /D "_WIN32_WCE=0x300" \ + /D "UNICODE" /D "_UNICODE" \ + /c msvc.cpp Property changes on: trunk/cegcc/tools/abicheck/makemsvc.sh ___________________________________________________________________ Name: svn:executable + * Name: svn:eol-style + native Added: trunk/cegcc/tools/abicheck/msvc.cpp =================================================================== --- trunk/cegcc/tools/abicheck/msvc.cpp (rev 0) +++ trunk/cegcc/tools/abicheck/msvc.cpp 2007-11-18 16:33:11 UTC (rev 1075) @@ -0,0 +1,93 @@ +#include <windows.h> +#include <stdio.h> + +#include "common.h" +#include "msvc.h" + +void +print_offsets (void) +{ +#define poffset(T, F) \ + printf("offsetof (%s::%s) = %i\n", #T, #F, offsetof (T, F)) + + printf("sizeof (struct T1) = %i\n", sizeof (struct T1)); + poffset(struct T1, f1); + poffset(struct T1, f2); + poffset(struct T1, f3); + poffset(struct T1, f4); + + printf("sizeof (struct T2) = %i\n", sizeof (struct T2)); + poffset(struct T2, f1); + poffset(struct T2, f2); + poffset(struct T2, f3); + poffset(struct T2, f4); + + printf("sizeof (struct T3) = %i\n", sizeof (struct T3)); + poffset(struct T3, f1); + poffset(struct T3, f2); + poffset(struct T3, f3); + poffset(struct T3, f4); +} + +void +test_struct64 (const char *s, struct struct64 dd) +{ + printf("test_struct64, dd = %I64x\n", dd); +} + +void +test_struct32 (const char *s, struct struct32 dd) +{ + printf("test_struct32, dd = %x\n", dd); +} + +void +test_ldouble(const char *s, long double ld) +{ + printf("test_uint64, ld = %lf\n", ld); +} + +void +test_uint64(const char *s, unsigned __int64 ll) +{ + printf("test_uint64, ll = %I64x\n", ll); +} + +struct struct64 +test_ret_struct64 (void) +{ + struct struct64 ddd = { 0x1122334455667788i64 }; + return ddd; +} + +struct struct32 +test_ret_struct32 (void) +{ + struct struct32 ddd = { 0x11223344 }; + return ddd; +} + +long double +test_ret_ldouble (void) +{ + return 1.2345678; +} + +double +test_ret_double (void) +{ + return 2.3456789; +} + +void +test_odd_regs64 (char a, __int64 b, char c, __int64 d, char e, __int64 f) +{ + printf("test_odd_regs64\n" + "\ta = %d\n" + "\tb = %I64x\n" + "\tc = %d\n" + "\td = %I64x\n" + "\te = %d\n" + "\tf = %I64x\n", + (int)a, b, (int)c, d, (int)e, f); +} Property changes on: trunk/cegcc/tools/abicheck/msvc.cpp ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/abicheck/msvc.h =================================================================== --- trunk/cegcc/tools/abicheck/msvc.h (rev 0) +++ trunk/cegcc/tools/abicheck/msvc.h 2007-11-18 16:33:11 UTC (rev 1075) @@ -0,0 +1,30 @@ +#ifndef MSVC_H +#define MSVC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "common.h" + +void print_offsets (void); + +void test_struct64 (const char *s, struct struct64 dd); +void test_struct32 (const char *s, struct struct32 dd); + +struct struct64 test_ret_struct64 (void); +struct struct32 test_ret_struct32 (void); + +long double test_ret_ldouble(void); +double test_ret_double(void); + +void test_ldouble(const char *s, long double ld); +void test_uint64(const char *s, unsigned __int64 ll); + +void test_odd_regs64(char a, __int64 b, char c, __int64 d, char e, __int64 f); + +#ifdef __cplusplus +} +#endif + +#endif Property changes on: trunk/cegcc/tools/abicheck/msvc.h ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/abicheck/msvc.obj =================================================================== (Binary files differ) Property changes on: trunk/cegcc/tools/abicheck/msvc.obj ___________________________________________________________________ Name: svn:mime-type + application/octet-stream This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |