-/*
+/* resolver.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sourceforge.net>
*
+ * This is a resolver process. This program reads hostnames from standard
+ * input and uses the standard system resolver to obtain the IP address (or
+ * addresses) and returns these as a line on standard output.
+ *
+ * $Id$
*/
+
#if defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif
#pragma comment(lib, "ws2_32")
#endif
-void Win32Error(LPCTSTR sz, HRESULT hr);
-LPSTR W2A(LPCWSTR wstr);
+void Win32Error(FILE *fp, LPCTSTR sz, HRESULT hr);
+void DumpData(LPCTSTR szLabel, LPBYTE pData, DWORD cbData);
int
_tmain(int argc, LPCTSTR argv[])
{
WSADATA wsd;
- struct addrinfo hints = {0};
- struct addrinfo *res = NULL;
- const char * hostname;
DWORD dwCookie = 0;
- int r = 0;
-
- if (argc < 2) {
- _ftprintf(stderr, _T("usage: resolver <hostname>\n"));
- return -1;
- }
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
- Win32Error(_T("WSAStartup failed"), GetLastError());
+ Win32Error(stderr, _T("WSAStartup failed"), GetLastError());
return -1;
}
return -1;
}
-#ifdef UNICODE
- hostname = W2A(argv[1]);
+ while (1) {
+ struct addrinfo hints = {0};
+ struct addrinfo *res = NULL;
+ LPSTR hostname;
+ TCHAR buffer[1024];
+ LPTSTR line, q, tname;
+ int r = 0, nc = 0;
+
+ line = _fgetts(buffer, 1024, stdin);
+ if (line == NULL)
+ break;
+
+ /* trim whitespace */
+ while(*line && _istspace(*line))
+ line++;
+ q = line + lstrlen(line) - 1;
+ while (q > line && *q && isspace(*q))
+ q--;
+ *++q = 0;
+
+#ifdef _UNICODE
+ nc = WideCharToMultiByte(CP_ACP, 0, line, -1, NULL, 0, NULL, NULL);
+ hostname = (LPSTR)_alloca(nc + 1);
+ WideCharToMultiByte(CP_ACP, 0, line, -1, hostname, nc, NULL, NULL);
#else
- hostname = argv[1];
+ hostname = line;
#endif
-
- dwCookie = GetCurrentProcessId();
- ZeroMemory(&hints, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- r = getaddrinfo(hostname, "", &hints, &res);
+ dwCookie++;
+ ZeroMemory(&hints, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_socktype = SOCK_STREAM;
+ r = getaddrinfo(hostname, "", &hints, &res);
-#ifdef UNICODE
- HeapFree(GetProcessHeap(), 0, (LPVOID)hostname);
+ if (r != 0) {
+ Win32Error(stdout, _T("error"), WSAGetLastError());
+ } else {
+ struct addrinfo *p = res;
+ while (p != NULL) {
+ char name[NI_MAXHOST];
+ /*
+ printf("fam:%x prot:%x len:%d res:%s\n",
+ p->ai_family, p->ai_protocol, p->ai_addrlen,
+ p->ai_canonname);
+ DumpData(_T("addrinfo"), (LPBYTE)p, sizeof(struct addrinfo));
+ */
+ getnameinfo(p->ai_addr, p->ai_addrlen,
+ name, NI_MAXHOST,
+ NULL, 0,
+ NI_NUMERICHOST | NI_NUMERICSERV);
+#ifdef _UNICODE
+ nc = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
+ tname = (LPWSTR)_alloca(nc + sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, name, -1, tname, nc);
+#else
+ tname = name;
#endif
-
- if (r != 0) {
- Win32Error(_T("getaddrinfo"), WSAGetLastError());
- } else {
- struct addrinfo *p = res;
- printf("%d", dwCookie);
- while (p != NULL) {
- char name[NI_MAXHOST];
- getnameinfo(p->ai_addr, p->ai_addrlen,
- name, NI_MAXHOST,
- NULL, 0,
- NI_NUMERICHOST | NI_NUMERICSERV);
- printf(" %s", name);
- p = p->ai_next;
+ _tprintf(_T("%s "), tname);
+ p = p->ai_next;
+ }
+ _tprintf(_T("\n"));
+ freeaddrinfo(res);
}
- printf("\n");
- freeaddrinfo(res);
+
+ fflush(stdout);
}
WSACleanup();
return 0;
}
-LPSTR
-W2A(LPCWSTR wstr)
+void
+Win32Error(FILE *fp, LPCTSTR szMessage, HRESULT hr)
{
- LPSTR str = NULL;
- int slen = 0;
-
- if (wstr == NULL)
- return NULL;
-
- slen = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
- str = HeapAlloc(GetProcessHeap(), 0, slen * sizeof(CHAR));
- if (str != NULL)
- slen = WideCharToMultiByte(CP_ACP, 0, wstr, slen, str, slen, NULL, NULL);
- return str;
+ LPTSTR lpBuffer = NULL;
+ DWORD dwLen = 0;
+
+ dwLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, (DWORD)hr, LANG_NEUTRAL,
+ (LPTSTR)&lpBuffer, 0, NULL);
+ if (dwLen < 1) {
+ dwLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_STRING
+ | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ _T("code 0x%1!08X!%n"), 0, LANG_NEUTRAL,
+ (LPTSTR)&lpBuffer, 0, (va_list *)&hr);
+ }
+ _ftprintf(fp, _T("%s"), szMessage);
+ if (dwLen > 0) {
+ _ftprintf(fp, _T(": "));
+ _ftprintf(fp, lpBuffer);
+ }
+ LocalFree((HLOCAL)lpBuffer);
}
void
-Win32Error(LPCTSTR sz, HRESULT hr)
+DumpData(LPCTSTR szLabel, LPBYTE pData, DWORD cbData)
{
- LPTSTR lpBuffer = NULL;
- TCHAR sBuffer[30];
-
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, (DWORD)hr, LANG_NEUTRAL,
- (LPTSTR)&lpBuffer, 0, NULL);
-
- _ftprintf(stderr, _T("%s: "), sz);
- if (lpBuffer == NULL) {
- lpBuffer = sBuffer;
- _ftprintf(stderr, _T("code: %08lX\n"), hr);
- } else {
- _ftprintf(stderr, lpBuffer);
+ TCHAR line[120];
+ DWORD cn = 0;
+ LPTSTR p = line, q = line + 40;
+ FillMemory(line, 80 * sizeof(TCHAR), 32);
+ _sntprintf(p, 80, _T("%s:"), szLabel);
+ p += lstrlen(szLabel) + 1;
+ *p = 32;
+ for (cn = 0; cn < cbData; cn++) {
+ if (cn % 16 == 0) {
+ _sntprintf(q, 80, _T("\n% 4d: "), cn);
+ p = line, q = line + 40;
+ _ftprintf(stdout, line);
+ FillMemory(line, 80 * sizeof(TCHAR), 32);
+ }
+ _stprintf(p, _T("%02x"), (int)pData[cn]);
+ _stprintf(q, _T("%c"),
+ _istprint(pData[cn]) ? (int)pData[cn] : _T('.'));
+ p += 2;
+ q += 1;
+ *p = _T(' ');
}
+ _stprintf(q, _T("\n"));
+ _ftprintf(stdout, line);
}