- Added daytime and quote of the day services - Use universal header and remove needless seperate dirs - Many bugfixes - Added to build, not yet included in install as it's still in the early stages
Tested in WinXP using both Windows and Linux clients. Not yet tried in ROS, Modified: trunk/reactos/apps/utils/net/directory.xml Deleted: trunk/reactos/apps/utils/net/tcpsvcs/chargen/ Added: trunk/reactos/apps/utils/net/tcpsvcs/chargen.c Deleted: trunk/reactos/apps/utils/net/tcpsvcs/daytime/ Added: trunk/reactos/apps/utils/net/tcpsvcs/daytime.c Deleted: trunk/reactos/apps/utils/net/tcpsvcs/discard/ Deleted: trunk/reactos/apps/utils/net/tcpsvcs/echo/ Added: trunk/reactos/apps/utils/net/tcpsvcs/echo.c Deleted: trunk/reactos/apps/utils/net/tcpsvcs/qotd/ Added: trunk/reactos/apps/utils/net/tcpsvcs/qotd.c Deleted: trunk/reactos/apps/utils/net/tcpsvcs/skelserver/ Added: trunk/reactos/apps/utils/net/tcpsvcs/skelserver.c Modified: trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.c Modified: trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.h Added: trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.rc Modified: trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.xml _____
Modified: trunk/reactos/apps/utils/net/directory.xml --- trunk/reactos/apps/utils/net/directory.xml 2005-09-28 21:43:54 UTC (rev 18141) +++ trunk/reactos/apps/utils/net/directory.xml 2005-09-28 22:33:55 UTC (rev 18142) @@ -1,30 +1,33 @@
<directory name="arp"> - <xi:include href="arp/arp.xml" /> + <xi:include href="arp/arp.xml" /> </directory> <directory name="finger"> - <xi:include href="finger/finger.xml" /> + <xi:include href="finger/finger.xml" /> </directory> <directory name="ftp"> - <xi:include href="ftp/ftp.xml" /> + <xi:include href="ftp/ftp.xml" /> </directory> <directory name="ipconfig"> - <xi:include href="ipconfig/ipconfig.xml" /> + <xi:include href="ipconfig/ipconfig.xml" /> </directory> <directory name="netstat"> - <xi:include href="netstat/netstat.xml" /> + <xi:include href="netstat/netstat.xml" /> </directory> <directory name="ping"> - <xi:include href="ping/ping.xml" /> + <xi:include href="ping/ping.xml" /> </directory> <directory name="route"> - <xi:include href="route/route.xml" /> + <xi:include href="route/route.xml" /> </directory> +<directory name="tcpsvcs"> + <xi:include href="tcpsvcs/tcpsvcs.xml" /> +</directory> <directory name="telnet"> - <xi:include href="telnet/telnet.xml" /> + <xi:include href="telnet/telnet.xml" /> </directory> <directory name="tracert"> - <xi:include href="tracert/tracert.xml" /> + <xi:include href="tracert/tracert.xml" /> </directory> <directory name="whois"> - <xi:include href="whois/whois.xml" /> + <xi:include href="whois/whois.xml" /> </directory> _____
Added: trunk/reactos/apps/utils/net/tcpsvcs/chargen.c --- trunk/reactos/apps/utils/net/tcpsvcs/chargen.c 2005-09-28 21:43:54 UTC (rev 18141) +++ trunk/reactos/apps/utils/net/tcpsvcs/chargen.c 2005-09-28 22:33:55 UTC (rev 18142) @@ -0,0 +1,111 @@
+#include <stdio.h> +#include <winsock2.h> +#include <tchar.h> +#include "tcpsvcs.h" + +DWORD WINAPI ChargenHandler(VOID* Sock_) +{ + DWORD Retval = 0; + SOCKET Sock = (SOCKET)Sock_; + + if (!GenerateChars(Sock)) { + _tprintf(_T("Char generation failed\n")); + Retval = 3; + } + + _tprintf(_T("Shutting connection down...\n")); + if (ShutdownConnection(Sock, FALSE)) { + _tprintf(_T("Connection is down.\n")); + } + else + { + _tprintf(_T("Connection shutdown failed\n")); + Retval = 3; + } + _tprintf(_T("Terminating thread\n")); + ExitThread(0); + + return Retval; +} + + +BOOL GenerateChars(SOCKET Sock) +{ + int i, + charIndex, /* internal loop */ + loopIndex; /* line loop */ + char ring[END-START]; + char *endring; + BOOL bLoop = TRUE; + + /* fill ring with printable characters */ + for (charIndex=0, i=START; i<=END; charIndex++, i++) + ring[charIndex] = i; + /* establish the end character in the ring */ + endring = &ring[charIndex]; + + /* where we will start output from */ + loopIndex = 0; + + while (bLoop) + { + /* if the loop index is equal to number of chars previously + * printed, start the loop from the beginning */ + if (loopIndex == END-START) + loopIndex = 0; + + /* start printing from char controled by loopIndex */ + charIndex = loopIndex; + for (i=0; i<LINESIZ; i++) + { + /* FIXME: Should send lines instead of chars to improve efficiency + * TCP will wait until it fills a packet anway before putting on + * the wire, so it's pointless to keep polling send */ + if (!SendChar(Sock, ring[charIndex])) + { + return FALSE; + } + /* if current char equal last char, reset */ + if (ring[charIndex] == *endring) + charIndex = 0; + else + charIndex++; + } + + if (bLoop) + if ((!SendChar(Sock, L'\r')) || (!SendChar(Sock, L'\n'))) + return FALSE; + + /* increment loop index to start printing from next char in ring */ + loopIndex++; + } + + return TRUE; +} + +BOOL SendChar(SOCKET Sock, TCHAR c) +{ + INT RetVal; + INT SentBytes; + + SentBytes = 0; + RetVal = send(Sock, &c, sizeof(TCHAR), 0); + /*FIXME: need to establish if peer closes connection, + not just report a socket error */ + if (RetVal > 0) + { + SentBytes += RetVal; + return TRUE; + } + else if (RetVal == SOCKET_ERROR) + { + _tprintf(("Socket error\n")); + return FALSE; + } + else + _tprintf(("unknown error\n")); + //WSAGetLastError() + + _tprintf(("Connection closed by peer.\n")); + return TRUE; +} Property changes on: trunk/reactos/apps/utils/net/tcpsvcs/chargen.c ___________________________________________________________________ Name: svn:eol-style + native _____
Added: trunk/reactos/apps/utils/net/tcpsvcs/daytime.c --- trunk/reactos/apps/utils/net/tcpsvcs/daytime.c 2005-09-28 21:43:54 UTC (rev 18141) +++ trunk/reactos/apps/utils/net/tcpsvcs/daytime.c 2005-09-28 22:33:55 UTC (rev 18142) @@ -0,0 +1,46 @@
+#include <stdio.h> +#include <winsock2.h> +#include <tchar.h> +#include <time.h> +#include "tcpsvcs.h" + +DWORD WINAPI DaytimeHandler(VOID* Sock_) +{ + struct tm *newtime; + time_t aclock; + TCHAR *pszTime; + DWORD Retval = 0; + SOCKET Sock = (SOCKET)Sock_; + + time(&aclock); + newtime = localtime(&aclock); + pszTime = _tasctime(newtime); + + SendTime(Sock, pszTime); + + _tprintf(_T("Shutting connection down...\n")); + if (ShutdownConnection(Sock, FALSE)) + _tprintf(_T("Connection is down.\n")); + else + { + _tprintf(_T("Connection shutdown failed\n")); + Retval = 3; + } + _tprintf(_T("Terminating thread\n")); + ExitThread(0); + + return Retval; +} + + +BOOL SendTime(SOCKET Sock, TCHAR *time) +{ + INT StringSize = strlen(time); + INT RetVal = send(Sock, time, sizeof(TCHAR) * StringSize, 0); + + if (RetVal == SOCKET_ERROR) + return FALSE; + + _tprintf(("Connection closed by peer.\n")); + return TRUE; +} Property changes on: trunk/reactos/apps/utils/net/tcpsvcs/daytime.c ___________________________________________________________________ Name: svn:eol-style + native _____
Added: trunk/reactos/apps/utils/net/tcpsvcs/echo.c --- trunk/reactos/apps/utils/net/tcpsvcs/echo.c 2005-09-28 21:43:54 UTC (rev 18141) +++ trunk/reactos/apps/utils/net/tcpsvcs/echo.c 2005-09-28 22:33:55 UTC (rev 18142) @@ -0,0 +1,71 @@
+#include <stdio.h> +#include <winsock2.h> +#include <tchar.h> +#include "tcpsvcs.h" + +DWORD WINAPI EchoHandler(VOID* Sock_) +{ + DWORD Retval = 0; + SOCKET Sock = (SOCKET)Sock_; + + if (!EchoIncomingPackets(Sock)) { + _tprintf(_T("Echo incoming packets failed\n")); + Retval = 3; + } + + _tprintf(_T("Shutting connection down...\n")); + if (ShutdownConnection(Sock, TRUE)) { + _tprintf(_T("Connection is down.\n")); + } + else + { + _tprintf(_T("Connection shutdown failed\n")); + Retval = 3; + } + _tprintf(_T("Terminating thread\n")); + ExitThread(0); + + return Retval; +} + + + +BOOL EchoIncomingPackets(SOCKET Sock) +{ + TCHAR ReadBuffer[BUF]; + INT Temp; + INT ReadBytes; + INT SentBytes; + + do { + ReadBytes = recv(Sock, ReadBuffer, BUF, 0); + if (ReadBytes > 0) { + _tprintf(_T("Received %d bytes from client\n"), ReadBytes); + + SentBytes = 0; + while (SentBytes < ReadBytes) { + Temp = send(Sock, ReadBuffer + SentBytes, + ReadBytes - SentBytes, 0); + if (Temp > 0) { + _tprintf(_T("Sent %d bytes back to client\n"), Temp); + SentBytes += Temp; + } + else if (Temp == SOCKET_ERROR) { + return FALSE; + } + else { + /* Client closed connection before we could reply to + all the data it sent, so quit early. */ + _tprintf(_T("Peer unexpectedly dropped connection!\n")); + return FALSE; + } + } + } + else if (ReadBytes == SOCKET_ERROR) { + return FALSE; + } + } while (ReadBytes != 0); + + _tprintf(("Connection closed by peer.\n")); + return TRUE; +} Property changes on: trunk/reactos/apps/utils/net/tcpsvcs/echo.c ___________________________________________________________________ Name: svn:eol-style + native _____
Added: trunk/reactos/apps/utils/net/tcpsvcs/qotd.c --- trunk/reactos/apps/utils/net/tcpsvcs/qotd.c 2005-09-28 21:43:54 UTC (rev 18141) +++ trunk/reactos/apps/utils/net/tcpsvcs/qotd.c 2005-09-28 22:33:55 UTC (rev 18142) @@ -0,0 +1,56 @@
+#include <stdio.h> +#include <winsock2.h> +#include <tchar.h> +#include <time.h> +#include "tcpsvcs.h" + +//these need putting in an RC file. +TCHAR Quotes[][MAX_QUOTE_BUF] = { + _T(""I have a penchant for mischief, property damage, stalking and cheesecake, of course" - kjk hyperion"), + _T(""Wow! I fixed a setmenu bug." - jimtabor"), + _T(""if the code is broken though, your free to call it ur own" - Alex Ionescu"), + _T(""i don't know about any bug; none exist; ReactOS is prefect" - filip2307"), + _T(""if you were kernel code, cutler would rewrite you." - Alex Ionescu"), + _T(""Looks like Hartmut is cleaning out his WC. working copy, that is" - WaxDragon") +}; + +DWORD WINAPI QotdHandler(VOID* Sock_) +{ + DWORD Retval = 0; + SOCKET Sock; + INT NumOfQuotes; + + Sock = (SOCKET)Sock_; + NumOfQuotes = sizeof(Quotes) / MAX_QUOTE_BUF; + + SendQuote(Sock, Quotes[1]); + + _tprintf(_T("Shutting connection down...\n")); + if (ShutdownConnection(Sock, FALSE)) + _tprintf(_T("Connection is down.\n")); + else + { + _tprintf(_T("Connection shutdown failed\n")); + Retval = 3; + } + _tprintf(_T("Terminating thread\n")); + ExitThread(0); + + return Retval; +} + + +BOOL SendQuote(SOCKET Sock, TCHAR* Quote) +{ + INT StringSize; + INT RetVal; + + StringSize = strlen(Quote); + RetVal = send(Sock, Quote, sizeof(TCHAR) * StringSize, 0); + + if (RetVal == SOCKET_ERROR) + return FALSE; + + _tprintf(("Connection closed by peer.\n")); + return TRUE; +} Property changes on: trunk/reactos/apps/utils/net/tcpsvcs/qotd.c ___________________________________________________________________ Name: svn:eol-style + native _____
Added: trunk/reactos/apps/utils/net/tcpsvcs/skelserver.c --- trunk/reactos/apps/utils/net/tcpsvcs/skelserver.c 2005-09-28 21:43:54 UTC (rev 18141) +++ trunk/reactos/apps/utils/net/tcpsvcs/skelserver.c 2005-09-28 22:33:55 UTC (rev 18142) @@ -0,0 +1,125 @@
+#include <stdio.h> +#include <winsock2.h> +#include <tchar.h> +#include "tcpsvcs.h" + + +DWORD WINAPI StartServer(LPVOID lpParam) +{ + const TCHAR* HostIP = "127.0.0.1"; + DWORD RetVal; + WSADATA wsaData; + PSERVICES pServices; + + pServices = (PSERVICES)lpParam; + + if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) + { + _tprintf(_T("WSAStartup() failed : %lu\n"), RetVal); + return -1; + } + + SOCKET ListeningSocket = SetUpListener(HostIP, htons(pServices->Port)); + if (ListeningSocket == INVALID_SOCKET) + { + _tprintf(_T("error setting up socket\n")); + return 3; + } + + _tprintf(_T("Waiting for connections...\n")); + while (1) + { + AcceptConnections(ListeningSocket, pServices->Service); + printf("Acceptor restarting...\n"); + } + + /* won't see this yet as we kill the service */ + _tprintf(_T("Detaching Winsock2...\n")); + WSACleanup(); + return 0; +} + + +SOCKET SetUpListener(const char* ServAddr, int Port) +{ + SOCKET Sock; + SOCKADDR_IN Server; + + Sock = socket(AF_INET, SOCK_STREAM, 0); + if (Sock != INVALID_SOCKET) + { + Server.sin_family = AF_INET; + Server.sin_addr.s_addr = htonl(INADDR_ANY); + Server.sin_port = Port; + if (bind(Sock, (SOCKADDR*)&Server, sizeof(SOCKADDR_IN)) != SOCKET_ERROR) + { + listen(Sock, SOMAXCONN); + return Sock; + } + else + printf("bind() failed\n"); + + } + return INVALID_SOCKET; +} + + + + +VOID AcceptConnections(SOCKET ListeningSocket, LPTHREAD_START_ROUTINE Service) +{ + SOCKADDR_IN Client; + SOCKET Sock; + INT nAddrSize = sizeof(Client); + DWORD ThreadID; + + while (1) + { + Sock = accept(ListeningSocket, (SOCKADDR*)&Client, &nAddrSize); + if (Sock != INVALID_SOCKET) + { + _tprintf(_T("Accepted connection from %s:%d\n"), + inet_ntoa(Client.sin_addr), ntohs(Client.sin_port)); + _tprintf(_T("About to create thread\n")); + CreateThread(0, 0, Service, (void*)Sock, 0, &ThreadID); + } + else + { + _tprintf(_T("accept() failed\n")); + return; + } + } +} + +BOOL ShutdownConnection(SOCKET Sock, BOOL bRec) +{ + /* Disallow any further data sends. This will tell the other side + that we want to go away now. If we skip this step, we don't + shut the connection down nicely. */ + if (shutdown(Sock, SD_SEND) == SOCKET_ERROR) + { + _tprintf(_T("Error in shutdown")); + return FALSE; + } + + /* Receive any extra data still sitting on the socket. After all + data is received, this call will block until the remote host + acknowledges the TCP control packet sent by the shutdown above. + Then we'll get a 0 back from recv, signalling that the remote + host has closed its side of the connection. */ + if (bRec) + { + char ReadBuffer[BUF]; + int NewBytes = recv(Sock, ReadBuffer, BUF, 0); + if (NewBytes == SOCKET_ERROR) + return FALSE; + else if (NewBytes != 0) + _tprintf(_T("FYI, received %d unexpected bytes during shutdown\n"), NewBytes); + } + + /* Close the socket. */ + if (closesocket(Sock) == SOCKET_ERROR) + return FALSE; + + return TRUE; +} Property changes on: trunk/reactos/apps/utils/net/tcpsvcs/skelserver.c ___________________________________________________________________ Name: svn:eol-style + native _____
Modified: trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.c --- trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.c 2005-09-28 21:43:54 UTC (rev 18141) +++ trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.c 2005-09-28 22:33:55 UTC (rev 18142) @@ -2,37 +2,49 @@
#include <winsock2.h> #include <tchar.h> #include "tcpsvcs.h" -#include "skelserver/skelserver.h" -#include "echo/echo.h" -#include "chargen/chargen.h"
+LPTHREAD_START_ROUTINE +ServiceHandler[NUM_SERVICES] = { + EchoHandler, + ChargenHandler, + DaytimeHandler, + NULL, + QotdHandler +}; + +INT ServicePort[NUM_SERVICES] = { + ECHO_PORT, + CHARGEN_PORT, + DAYTIME_PORT, + DISCARD_PORT, + QOTD_PORT +}; + int main(int argc, char *argv[]) { - PMYDATA pData[MAX_THREADS]; - DWORD dwThreadId[MAX_THREADS]; - HANDLE hThread[MAX_THREADS]; + PSERVICES pServices[NUM_SERVICES]; + DWORD dwThreadId[NUM_SERVICES]; + HANDLE hThread[NUM_SERVICES]; INT i;
/* Create MAX_THREADS worker threads. */ - for( i=0; i<MAX_THREADS; i++ ) + for( i=0; i<NUM_SERVICES; i++ ) { /* Allocate memory for thread data. */ - pData[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA)); - - if( pData == NULL ) + pServices[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SERVICES)); + + if( pServices[i] == NULL ) ExitProcess(2);
/* Generate unique data for each thread. */ - pData[0]->Port = ECHO_PORT; - pData[0]->Service = EchoHandler; - pData[1]->Port = CHARGEN_PORT; - pData[1]->Service = ChargenHandler; + pServices[i]->Service = ServiceHandler[i]; + pServices[i]->Port = ServicePort[i];
hThread[i] = CreateThread( NULL, // default security attributes 0, // use default stack size StartServer, // thread function - pData[i], // argument to thread function + pServices[i], // argument to thread function 0, // use default creation flags &dwThreadId[i]); // returns the thread identifier
@@ -44,14 +56,13 @@ }
/* Wait until all threads have terminated. */ - WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE); + WaitForMultipleObjects(NUM_SERVICES, hThread, TRUE, INFINITE);
/* Close all thread handles upon completion. */ - for(i=0; i<MAX_THREADS; i++) + for(i=0; i<NUM_SERVICES; i++) { CloseHandle(hThread[i]); }
return 0; } - _____
Modified: trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.h --- trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.h 2005-09-28 21:43:54 UTC (rev 18141) +++ trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.h 2005-09-28 22:33:55 UTC (rev 18142) @@ -1,3 +1,4 @@
+/* default port numbers */ #define ECHO_PORT 7 #define CHARGEN_PORT 19 #define DAYTIME_PORT 13 @@ -4,10 +5,49 @@ #define DISCARD_PORT 9 #define QOTD_PORT 17
-#define MAX_THREADS 2 +#define NUM_SERVICES 6 #define BUF_SIZE 255 +#define BUF 1024
-typedef struct _MyData { +/* RFC865 states no more than 512 chars per line */ +#define MAX_QUOTE_BUF 512 + +/* printable ASCII's characters for chargen */ +#define START 32 +#define END 126 + +/* number of chars to put on a line */ +#define LINESIZ 72 + +/* data structure to pass to threads */ +typedef struct _Services { INT Port; LPTHREAD_START_ROUTINE Service; -} MYDATA, *PMYDATA; +} SERVICES, *PSERVICES; + +/* skelserver functions */ +DWORD WINAPI StartServer(LPVOID lpParam); +SOCKET SetUpListener(const char* ServAddr, int Port); +VOID AcceptConnections(SOCKET ListeningSocket, LPTHREAD_START_ROUTINE Service); +BOOL EchoIncomingPackets(SOCKET sd); +BOOL ShutdownConnection(SOCKET Sock, BOOL bRec); + +/* chargen functions */ +DWORD WINAPI ChargenHandler(VOID* Sock_); +BOOL GenerateChars(SOCKET Sock); +BOOL SendChar(SOCKET Sock, CHAR c); + +/* daytime functions */ +DWORD WINAPI DaytimeHandler(VOID* Sock_); +BOOL SendTime(SOCKET Sock, TCHAR *time); + +/* echo functions */ +DWORD WINAPI EchoHandler(VOID* Sock_); +BOOL EchoIncomingPackets(SOCKET Sock); + +/* discard functions */ + + +/* qotd functions */ +DWORD WINAPI QotdHandler(VOID* Sock_); +BOOL SendQuote(SOCKET Sock, TCHAR* Quote); _____
Added: trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.rc --- trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.rc 2005-09-28 21:43:54 UTC (rev 18141) +++ trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.rc 2005-09-28 22:33:55 UTC (rev 18142) @@ -0,0 +1,7 @@
+#include "resource.h" + +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS TCP/IP Services Application\0" +#define REACTOS_STR_INTERNAL_NAME "tcpsvcs\0" +#define REACTOS_STR_ORIGINAL_FILENAME "tcpsvcs.exe\0" +#define REACTOS_STR_ORIGINAL_COPYRIGHT "Ged Murphy (gedmurphy@gmail.com)\0" +#include <reactos/version.rc> Property changes on: trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.rc ___________________________________________________________________ Name: svn:eol-style + native _____
Modified: trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.xml --- trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.xml 2005-09-28 21:43:54 UTC (rev 18141) +++ trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.xml 2005-09-28 22:33:55 UTC (rev 18142) @@ -1,13 +1,15 @@
-<module name="tcpsvcs" type="win32cui" installbase="system32" installname="tcpsvcs.exe"> - <include base="arp">.</include> - <define name="__USE_W32API" /> - <library>kernel32</library> - <library>iphlpapi</library> - <library>ws2_32</library> - <library>shlwapi</library> - <file>tcpsvcs.c</file> - <file>skelserver/skelserver.c</file> - <file>echo/echo.c</file> - <file>chargen/chargen.c</file> -</module> - +<module name="tcpsvcs" type="win32cui" installbase="system32" installname="tcpsvcs.exe"> + <include base="arp">.</include> + <define name="__USE_W32API" /> + <library>kernel32</library> + <library>iphlpapi</library> + <library>ws2_32</library> + <library>shlwapi</library> + <file>tcpsvcs.c</file> + <file>skelserver.c</file> + <file>echo.c</file> + <file>chargen.c</file> + <file>daytime.c</file> + <file>qotd.c</file> +</module> + Property changes on: trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.xml ___________________________________________________________________ Name: svn:eol-style + native