Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

417 lines
9.9 KiB

/*++
goph.c
History:
Richard Firth ( RFirth) Created
Murali Krishnan ( Modified to send output to file)
Murali Krishnan ( added filter for tabs) 16-Nov-1994
--*/
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <io.h>
#include <errno.h>
#ifndef _CRTAPI1
#define _CRTAPI1
#endif
#define K * 1024
#define _4K (4 K)
#define _8K (8 K)
#define _16K (16 K)
#define _32K (32 K)
#define IS_ARG(c) (((c) == '-') || ((c) == '/'))
#define ROUND_UP_4K(n) (((n) + (_4K - 1)) & -_4K)
#define ROUND_UP_8K(n) (((n) + (_8K - 1)) & -_8K)
#define ROUND_UP_16K(n) (((n) + (_16K - 1)) & -_16K)
#define ROUND_UP_32K(n) (((n) + (_32K - 1)) & -_32K)
#define ROUND_UP(n, k) (((n) + (_ ## K - 1)) & -_ ## K)
void _CRTAPI1 main(int, char**);
void usage( char * pszProg);
void _CRTAPI1 cleanup(void);
int Verbose = 0;
int NoCrLf = 0;
int Port = 70;
int Timeout = 30;
static char *
TranslateTabs( char * pszSelector)
{
if ( pszSelector != NULL) {
char * pszScan;
for( pszScan = pszSelector; *pszScan ; pszScan++) {
if ( *pszScan == '#') {
*pszScan = '\t'; // convert # to tabs
}
} // for
}
return ( pszSelector);
} // TranslateTabs()
void _CRTAPI1 main(int argc, char** argv) {
int err;
WSADATA wsaData;
SOCKADDR_IN sockAddr;
SOCKET sock;
LPSTR buffer;
LPBYTE bufptr;
LPSTR ptr;
DWORD len;
int n;
int bytesReceived;
LPSTR host = NULL;
LPSTR selector = NULL;
DWORD bufsiz;
DWORD bufLeft;
DWORD nextBlock;
DWORD transferLen;
fd_set read_set;
TIMEVAL tv;
char* filename = NULL;
FILE * fpOutput = stdout;
int fh;
for (--argc, ++argv; argc; --argc, ++argv) {
if (IS_ARG(**argv)) {
switch (*++*argv) {
case 'f':
filename = ++*argv;
break;
case 'n':
NoCrLf = 1;
break;
case 'p':
Port = atoi(++*argv);
break;
case 't':
Timeout = (DWORD)atoi(++*argv);
break;
case 'v':
Verbose = 1;
break;
default:
printf("error: unrecognized command line flag: '%c'\n", **argv);
usage( argv[0]);
}
} else if (!host) {
host = *argv;
} else if (!selector) {
selector = TranslateTabs(*argv);
} else {
printf("error: \"%s\"?\n", *argv);
usage( argv[0]);
}
}
if (!host) {
printf("error: must specify host server\n");
usage( argv[0]);
}
//
// 1. initialize winsock
//
if (err = WSAStartup(0x0101, &wsaData)) {
printf("error: WSAStartup() returns %d\n", err);
exit(1);
}
atexit(cleanup);
if (filename) {
if ((fpOutput = fopen(filename, "w+b")) == NULL) {
printf("error: fopen(%s) returns %d\n", filename, errno);
fpOutput = stdout;
}
} else {
fpOutput = stdout;
}
//
// 2. get IP address to connect to
//
sockAddr.sin_addr.s_addr = inet_addr(host);
if (sockAddr.sin_addr.s_addr == INADDR_NONE) {
LPHOSTENT lph;
lph = gethostbyname(host);
if (!lph) {
printf("error: gethostbyname(%s) returns %d\n", host, WSAGetLastError());
exit(1);
} else {
sockAddr.sin_addr.s_addr = *(DWORD*)lph->h_addr;
}
}
//
// 3. create socket
//
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
printf("error: socket() returns %d\n", WSAGetLastError());
exit(1);
} else if (Verbose) {
printf("socket created Ok\n");
}
//
// 4. connect to server
//
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(Port);
if (connect(sock, (LPSOCKADDR)&sockAddr, sizeof(sockAddr))) {
printf("error: connect() returns %d\n", WSAGetLastError());
exit(1);
} else if (Verbose) {
printf("connected to server Ok\n");
}
//
// 5. send request
//
if (selector) {
ptr = selector;
len = strlen(ptr);
} else {
ptr = NULL;
len = 0;
}
transferLen = 0;
while (len) {
int val;
val = send(sock, ptr, len, 0);
if (val == SOCKET_ERROR) {
printf("error: send() returns %d\n", WSAGetLastError());
exit(1);
} else {
ptr += val;
len -= val;
transferLen += val;
}
}
//
// 5A. request is terminated with CR/LF
//
if (!NoCrLf) {
ptr = "\r\n";
len = 2;
while (len) {
int val;
val = send(sock, ptr, len, 0);
if (val == SOCKET_ERROR) {
printf("error: send() returns %d\n", WSAGetLastError());
exit(1);
} else {
ptr += val;
len -= val;
transferLen += val;
}
}
}
if (Verbose) {
printf("%d bytes sent to host\n", transferLen);
}
//
// 6. get response
//
len = 64 * 1024;
buffer = (LPBYTE)LocalAlloc(LMEM_FIXED, len);
if (!buffer) {
printf("error: couldn't allocate %d byte buffer\n", len);
exit(1);
} else if (Verbose) {
printf("allocated %d byte buffer\n", len);
}
bytesReceived = 0;
transferLen = 0;
bufptr = buffer;
bufsiz = len;
bufLeft = bufsiz;
if (Verbose) {
printf("waiting for data to arrive\n");
}
FD_ZERO(&read_set);
FD_SET(sock, &read_set);
do {
tv.tv_sec = (long)Timeout;
tv.tv_usec = 0;
n = select(0, &read_set, NULL, NULL, &tv);
if (n <= 0) {
if (n == 0) {
printf("error: select() timed out\n");
} else {
printf("error: select() returns %d, %d\n", n, WSAGetLastError());
}
exit(1);
} else if (Verbose) {
printf("info: select() returns %d\n", n);
}
if (Verbose && (tv.tv_sec != 5 || tv.tv_usec)) {
printf("INFO: timeval got zapped: tv_sec=%d tv_usec=%d\n", tv.tv_sec, tv.tv_usec);
}
err = ioctlsocket(sock, FIONREAD, &nextBlock);
if (err) {
printf("error: ioctlsocket(FIONREAD) returns %d, %d\n", err, WSAGetLastError());
exit(1);
} else if (Verbose) {
printf("nextBlock = %d\n", nextBlock);
}
#if 0 // muralik
if (nextBlock > bufLeft) {
LPBYTE oldBuf;
DWORD oldNb;
oldNb = nextBlock;
nextBlock = ROUND_UP_32K(nextBlock);
if (Verbose) {
printf("nextBlock rounded-up from %d to %d\n", oldNb, nextBlock);
}
oldBuf = buffer;
len += nextBlock;
buffer = LocalReAlloc((HLOCAL)buffer, len, 0);
if (!buffer) {
printf("error: LocalReAlloc(%d) returns %d\n", len, GetLastError());
exit(1);
} else if (Verbose) {
printf("buffer @%x realloc'd Ok\n", buffer);
if (oldBuf != buffer) {
printf("INFO: oldBuf (%x) != buffer (%x)\n", oldBuf, buffer);
} else {
printf("INFO: oldBuf (%x) == buffer (%x)\n", oldBuf, buffer);
}
}
bufptr = buffer + transferLen;
bufLeft += nextBlock;
}
#endif // muralik
if (nextBlock) {
n = recv(sock, bufptr, bufLeft, 0);
if (n < 0) {
printf("error: recv() returns %d, %d\n", n, WSAGetLastError());
break;
} else if (n) {
if (Verbose) {
printf("%d bytes received\n", n);
if (n != nextBlock) {
printf("ERROR?: ioctlsocket(FIONREAD) (%d) != recv() (%d)\n", nextBlock, n);
}
}
fwrite( bufptr, 1, n, fpOutput);
// bufptr += n;
bytesReceived += n;
transferLen += n;
// bufLeft -= n;
}
}
} while ( nextBlock );
if (!nextBlock) {
printf("nextBlock == 0: end-of-response. %d bytes total received\n", transferLen);
}
if (n == 0) {
printf("0 bytes received: done\n");
}
//
// 7. close socket
//
if (closesocket(sock)) {
printf("error? closesocket() returns %d\n", WSAGetLastError());
} else {
printf("socket closed ok\n");
}
//
// 8. dump info
//
// printf("%s\n", buffer);
// close(1);
// if (open("stdout", _O_CREAT | _O_BINARY | _O_WRONLY, _S_IWRITE) < 0) {
// fprintf(stderr, "couldn't open stdout! errno = %d\n", errno);
// }
if (fpOutput != NULL) {
fclose(fpOutput);
}
//
// 9. done
//
printf("Done.\n");
exit(0);
}
void usage(char * pszProg) {
printf("\n"
"usage: %s [-n] [-p#] [-t#] [-v] <gopher server> [<selector>]\n"
"\n"
"where: -n = don't append CR/LF to <selector>\n"
" -p = connect to port # at server. Default is %d\n"
" -t = timeout for select() in seconds. Default is %d Sec.\n"
" -v = verbose mode\n"
" <gopher server> is an IP address or host name\n"
" <selector> is gopher identifier\n",
pszProg,
Port,
Timeout
);
exit(1);
}
void _CRTAPI1 cleanup() {
int err;
err = WSACleanup();
if (err) {
printf("cleanup: WSACleanup() returns %d\n", WSAGetLastError());
}
}