public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* problem building a dll that uses other dll's
@ 1997-08-22 12:21 Dan Goldwater
  0 siblings, 0 replies; 3+ messages in thread
From: Dan Goldwater @ 1997-08-22 12:21 UTC (permalink / raw)
  To: gnu-win32

Hi!
I am trying to build a DLL which has function calls which must be
resolved into existing win32 DLL's.

I am using b18 on winNT 4.0.  i have MSVC 5.0 available.

Following the instructions for building a relocatable dll, i get an
output but each of the three ld steps reports all the undefined
references for the functions which are in the existing win32 dll's.  i had
to add the --noinhibit-exec option to ld so that it wouldn't delete the
output dll due to the errors.  if i try to use the result dll, it says it 
is an invalid image...

when i build this project on solaris, the linker doesn't complain about the
undefined references, and they are resolved to appropriate existing .so
files at runtime.

is there some option i need to give ld so it knows i want to resolve the
references at runtime to the existing dll's?  or am i clueless?

thanks!

---------------------------------------------------------
Dan Goldwater          dgold@brown.edu
http://fatmac.ee.cornell.edu/~goldwada
---------------------------------------------------------


-
For help on using this list (especially unsubscribing), send a message to
"gnu-win32-request@cygnus.com" with one line of text: "help".

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: problem building a dll that uses other dll's
       [not found] ` <199708251852.OAA02984@nut.brown.edu>
@ 1997-08-25 23:11   ` Mikey
  0 siblings, 0 replies; 3+ messages in thread
From: Mikey @ 1997-08-25 23:11 UTC (permalink / raw)
  To: dgold, gnu-win32

[-- Attachment #1: Type: text/plain, Size: 1531 bytes --]

These are from the SDK_4_ming_cygwin32
lib2def does the obvious, the Makefile
should show you how to use it.

If you don't have the .lib file, you can use impdef.exe
to generate the .def file, you may need to edit it
to eliminate c++ junk, (vc++ has different
name mangling conventions then g++)

just redirect the output of impdef to a file, then
run dlltool on it as shown in the enclosed Makefile.

On Mon, 25 Aug 1997 14:54:39 -500, you wrote:

>> The dll is not the stub library, the stub library
>> for foo.dll is libfoo.a
>
>ok, the thing is that i don't have the stub library for foo.dll.  foo.dll
>is from a commercial product.  does this mean i'm stuck?  if i had the .a 
>files i would have been all set long ago :)
>
>is there some way to generate the .a file for foo.dll?
>
>> BTW all of this stuff is in the ld man page, and also
>> in gcc.info, you might try reading them.
>
>really i already knew all the basics of ld, the stuff i'm having the 
>problem with is specific to gnuwin32.

Then why are you asking about -l "small L"?

One of the basics of ld, is that you don't link directly with coff or aout
shared libraries, you have to make a stub library first.

That's the main reason why linux when to ELF.

>
>thanks.
>---------------------------------------------------------
>Dan Goldwater          dgold@brown.edu
> http://fatmac.ee.cornell.edu/~goldwada
>---------------------------------------------------------
>
>
>

(jeffdbREMOVETHIS@netzone.com)
delete REMOVETHIS from the above to reply
         Mikey

[-- Attachment #2: impdef.c --]
[-- Type: text/x-c, Size: 10780 bytes --]

//==================================
// This is a modification of:
//   PEDUMP - Matt Pietrek 1995
// done by Ismael Jurado 1997
//
// This program only outputs to stdout a DEF file from a DLL given in the
// command line.
// I don´t know how to contact Matt, so if this program is not legal, please
// let me know.
//    ismaelj@hotmail.com
//==================================

#include <windows.h>
#include <stdio.h>
int flag2 = 1;

// This code was taken from WINNT.H, which is not included in the current
// Cygnus port.
#ifndef _WINNT_
#define FIELD_OFFSET(type, field)    ((LONG)&(((type *)0)->field))
#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER)       \
    ((DWORD)ntheader +                                                 \
     FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) +                \
     ((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader  \
    ))

#define IMAGE_SIZEOF_SHORT_NAME              8
#define IMAGE_DIRECTORY_ENTRY_EXPORT         0   // Export Directory
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16
#define IMAGE_NT_SIGNATURE                  0x00004550  // PE00
#define IMAGE_DOS_SIGNATURE                 0x5A4D      // MZ

typedef struct _IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress;
    DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;
    WORD    NumberOfSections;
    DWORD   TimeDateStamp;
    DWORD   PointerToSymbolTable;
    DWORD   NumberOfSymbols;
    WORD    SizeOfOptionalHeader;
    WORD    Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

typedef struct _IMAGE_OPTIONAL_HEADER {
    //
    // Standard fields.
    //

    WORD    Magic;
    BYTE    MajorLinkerVersion;
    BYTE    MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;

    //
    // NT additional fields.
    //

    DWORD   ImageBase;
    DWORD   SectionAlignment;
    DWORD   FileAlignment;
    WORD    MajorOperatingSystemVersion;
    WORD    MinorOperatingSystemVersion;
    WORD    MajorImageVersion;
    WORD    MinorImageVersion;
    WORD    MajorSubsystemVersion;
    WORD    MinorSubsystemVersion;
    DWORD   Reserved1;
    DWORD   SizeOfImage;
    DWORD   SizeOfHeaders;
    DWORD   CheckSum;
    WORD    Subsystem;
    WORD    DllCharacteristics;
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    DWORD   SizeOfHeapReserve;
    DWORD   SizeOfHeapCommit;
    DWORD   LoaderFlags;
    DWORD   NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;


typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;

typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;
    DWORD   SizeOfRawData;
    DWORD   PointerToRawData;
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;
    DWORD   TimeDateStamp;
    WORD    MajorVersion;
    WORD    MinorVersion;
    DWORD   Name;
    DWORD   Base;
    DWORD   NumberOfFunctions;
    DWORD   NumberOfNames;
    PDWORD  *AddressOfFunctions;
    PDWORD  *AddressOfNames;
    PWORD   *AddressOfNameOrdinals;
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
    WORD   e_magic;                     // Magic number
    WORD   e_cblp;                      // Bytes on last page of file
    WORD   e_cp;                        // Pages in file
    WORD   e_crlc;                      // Relocations
    WORD   e_cparhdr;                   // Size of header in paragraphs
    WORD   e_minalloc;                  // Minimum extra paragraphs needed
    WORD   e_maxalloc;                  // Maximum extra paragraphs needed
    WORD   e_ss;                        // Initial (relative) SS value
    WORD   e_sp;                        // Initial SP value
    WORD   e_csum;                      // Checksum
    WORD   e_ip;                        // Initial IP value
    WORD   e_cs;                        // Initial (relative) CS value
    WORD   e_lfarlc;                    // File address of relocation table
    WORD   e_ovno;                      // Overlay number
    WORD   e_res[4];                    // Reserved words
    WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
    WORD   e_oeminfo;                   // OEM information; e_oemid specific
    WORD   e_res2[10];                  // Reserved words
    LONG   e_lfanew;                    // File address of new exe header
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
#endif // __WINNT__

// Here starts Matt's code
//
//
// MakePtr is a macro that allows you to easily add to values (including
// pointers) together without dealing with C's pointer arithmetic.  It
// essentially treats the last two parameters as DWORDs.  The first
// parameter is used to typecast the result to the appropriate pointer type.
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (DWORD)(addValue))
PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva,
                                                PIMAGE_NT_HEADERS pNTHeader)
{
    PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
    unsigned i;

    for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ ) {
        // Is the RVA within this section?
        if ( (rva >= section->VirtualAddress) &&
             (rva < (section->VirtualAddress + section->Misc.VirtualSize)))
            return section;
    }
    return 0;
}

void DumpExportsSection(DWORD base, PIMAGE_NT_HEADERS pNTHeader) {
    PIMAGE_EXPORT_DIRECTORY exportDir;
    PIMAGE_SECTION_HEADER header;
    INT delta;
    DWORD i;
    PDWORD functions;
    PWORD ordinals;
    PSTR *name;
    DWORD exportsStartRVA, exportsEndRVA;

    exportsStartRVA = pNTHeader->OptionalHeader.DataDirectory [IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    exportsEndRVA = exportsStartRVA + pNTHeader->OptionalHeader.DataDirectory [IMAGE_DIRECTORY_ENTRY_EXPORT].Size;

    // Get the IMAGE_SECTION_HEADER that contains the exports.  This is
    // usually the .edata section, but doesn't have to be.
    header = (PIMAGE_SECTION_HEADER)GetEnclosingSectionHeader( exportsStartRVA, pNTHeader );
    if ( !header ) return;
    delta = (INT)(header->VirtualAddress - header->PointerToRawData);
    exportDir = MakePtr(PIMAGE_EXPORT_DIRECTORY, base, exportsStartRVA - delta);


    if (flag2)
    printf("EXPORTS\n");

    functions = (PDWORD)((DWORD)exportDir->AddressOfFunctions - delta + base);
    ordinals = (PWORD)((DWORD)exportDir->AddressOfNameOrdinals - delta + base);
    name = (PSTR *)((DWORD)exportDir->AddressOfNames - delta + base);
    for ( i=0; i < exportDir->NumberOfFunctions; i++ ) {
        DWORD entryPointRVA = functions[i];
        DWORD j;
        int flag=0;

        if ( entryPointRVA == 0 )   // Skip over gaps in exported function
            continue;               // ordinals (the entrypoint is 0 for
                                    // these functions).
        // See if this function has an associated name exported for it.
        for ( j=0; j < exportDir->NumberOfNames; j++ )
            if ( ordinals[j] == i ) {
                printf("%s", name[j] - delta + base);

		if (flag2)
		printf("\t@%u", i + exportDir->Base);

                flag=1;
            }
        // Is it a forwarder?  If so, the entry point RVA is inside the
        // .edata section, and is an RVA to the DllName.EntryPointName
        if ( (entryPointRVA >= exportsStartRVA)&&(entryPointRVA <= exportsEndRVA) )
        {
            printf("%s", entryPointRVA - delta + base);

	    if (flag2)
	    printf("\t@%u", i + exportDir->Base);

            flag=1;
        }

        if (flag) printf("\n");
    }
}

void DumpExeFile( PIMAGE_DOS_HEADER dosHeader )
{
    PIMAGE_NT_HEADERS pNTHeader;
    DWORD base = (DWORD)dosHeader;

    pNTHeader = MakePtr( PIMAGE_NT_HEADERS, dosHeader,
                                dosHeader->e_lfanew );

    // First, verify that the e_lfanew field gave us a reasonable
    // pointer, then verify the PE signature.
    // IJ: gcc doesn't support C exeptions??
//    __try
//    {
        if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
        {
            printf("Not a Portable Executable (PE) EXE\n");
            return;
        }
//    }
/*
    __except( TRUE )    // Should only get here if pNTHeader (above) is bogus
    {
        printf( "invalid .EXE\n");
        return;
    }
*/
    DumpExportsSection(base, pNTHeader);
    printf("\n");
}

void DumpFile(LPSTR filename)
{
    HANDLE hFile;
    HANDLE hFileMapping;
    LPVOID lpFileBase;
    PIMAGE_DOS_HEADER dosHeader;
    
    hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

    if ( hFile == INVALID_HANDLE_VALUE )
    {
        printf("Couldn't open file with CreateFile()\n");
        return;
    }

    hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
    if ( hFileMapping == 0 )
    {
        CloseHandle(hFile);
        printf("Couldn't open file mapping with CreateFileMapping()\n");
        return;
    }

    lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
    if ( lpFileBase == 0 )
    {
        CloseHandle(hFileMapping);
        CloseHandle(hFile);
        printf("Couldn't map view of file with MapViewOfFile()\n");
        return;
    }

    if (flag2)
    printf(";Exports of file %s\n\n", filename);
    
    dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
    if ( dosHeader->e_magic == IMAGE_DOS_SIGNATURE )
    {
        DumpExeFile( dosHeader );
    }
    else printf("Format Unknown!\n");
}

char HelpText[] =
"IMPDEF\n"
"Syntax: IMPDEF DLLname\n\n"
"Modification of:\n"
"PEDUMP - Win32/COFF EXE/OBJ/LIB file dumper - 1995 Matt Pietrek\n"
"by Ismael Jurado 1997. Only produces a DEF file from a DLL\n"
"Let me know if this modification is not legal: ismaelj@hotmail.com\n";

int main(int argc, char *argv[]) {
  if ( argc == 1 ) {
    printf( HelpText );
    return 1;
  }
  if (argc == 3 && *argv[1] == '-')
  {
  flag2 = 0;
  DumpFile(argv[2]);
  }
  else
  {
  DumpFile(argv[1]);
  }
  return 0;
}

[-- Attachment #3: lib2def --]
[-- Type: text/x-shellscript, Size: 519 bytes --]

#!/bin/sh

tlow(){
echo $1|tr A-Z a-z
}

if [ x"$1" = x"" ];then
  echo "shell script to generate .def files from .LIB files
  $0 filename ..."
  exit 0
else
  echo LIBRARY `basename $1 .lib` 
  echo EXPORTS
  echo fakefunc$RANDOM
  nm --extern-only $1|egrep '^........ [TR]' \
  |fgrep -v '$AA'\
  |fgrep -v 'C@_0'\
  |fgrep -v '@@' \
  |sort \
  |sed -e 's/[^_]*_//' -e 's/[^?]*?//' 
fi

# T= .text section R= readonly .data section (exported variables)
# $AA C@_0 @@ exported structure/internal function definitions

[-- Attachment #4: Makefile --]
[-- Type: text/x-makefile, Size: 2961 bytes --]

.PHONY: all install clean distclean uninstall distuninstall

#these are here to be overidden from the command line or the top level Makefile

prefix = `gcc -print-file-name=crt0.o|sed -e s/\\\\\\\\/\\\\//g -e s/\\\\/i386-cygwin32\\\\/lib\\\\/crt0.o//`
exec_prefix  := $(shell echo ${prefix})
SDK=/m/mstools
SDKD =  ${SDK}

ifeq "$(findstring i386-cygwin32,$(exec_prefix))" "i386-cygwin32"
INSTALLDIR=$(exec_prefix)/i386-cygwin32/lib
else
INSTALLDIR=$(exec_prefix)/lib
endif


.SUFFIXES: $(SUFFIXES) .lib .LIB .def .dll .a


OURLIBS= libcrtdll.a liblargeint.a liboldnames.a

BASELIBS= \
	libadvapi32.a \
	libcomctl32.a \
	libcomdlg32.a \
	libgdi32.a \
	libimm32.a \
	libkernel32.a \
	liblsapi32.a \
	libmswsock.a \
	libnetapi32.a \
	libole32.a \
	liboleaut32.a \
	librasapi32.a \
	libshell32.a \
	libuser32.a \
	libuuid.a \
	libversion.a \
	libwinmm.a \
	libwinspool.a \
	libws2_32.a \
	libwsock32.a \



CYGLIBS= \
	libcap.a \
	libctl3d32.a \
	libdlcapi.a \
	libglu32.a \
	libicmp.a \
	liblargeint.a \
	liblz32.a \
	libmapi32.a \
	libmfcuia32.a \
	libmgmtapi.a \
	libmpr.a \
	libmsacm32.a \
	libnddeapi.a \
	libodbc32.a \
	libodbccp32.a \
	liboledlg.a \
	libolepro32.a \
	libopengl32.a \
	libpenwin32.a \
	libpkpd32.a \
	librpcdce4.a \
	librpcndr.a \
	librpcns4.a \
	librpcrt4.a \
	libscrnsave.a \
	libsnmp.a \
	libsvrapi.a \
	libtapi32.a \
	libth32.a \
	libthunk32.a \
	liburl.a \
	libvdmdbg.a \
	libvfw32.a \
	libwin32spl.a \
	libwinserve.a \
	libwinstrm.a \
	libwow32.a \
	libwst.a \


SDKLIBS=$(addprefix lib,$(addsuffix .a,$(basename $(notdir $(wildcard $(SDK)/lib/*.lib)))))


all: $(OURLIBS) $(BASELIBS)

install-mylib:
	install *.a $(INSTALLDIR)/

libcrtdll.a: crtdll.def
	dlltool --dllname crtdll.dll --def $< --output-lib $@ -k

liblargeint.a: largeint.def
	dlltool --dllname crtdll.dll --def $< --output-lib $@ -k

liboldnames.a: oldnames.def
	dlltool --dllname crtdll.dll --def $< --output-lib $@ -k

%.def: $(SDK)/lib/%.lib
	set -xv;\
	[ -d obj/i386/ ] || mkdir -p obj/i386/;\
	cp $< . ;\
	Objs=`ar -t $(notdir $<)|grep -v \\.dll`;\
	[ -z "$$Objs" ] && exit 0;\
	ar -x $(notdir $<) $$Objs;\
	ar -d $(notdir $<) $$Objs;\
	for file in $$Objs;do \
	  objcopy $$file `basename $$file .obj`.o;\
	  rm $$file;\
	done
	../bin/lib2def $(notdir $<) > $@
	rm $(notdir $<)

lib%.a: %.def
	dlltool --dllname $*.dll  --def $<  --output-lib $@ -k
	set -xv;\
	Objs=`echo *.o`;\
	[ "$$Objs" = "*.o" ] && exit 0;\
	ar urvs $@ $$Objs;\
	rm *.o

# to keep a copy of the .def files uncomment the next 6 lines
#%.def: $(SDK)/lib/%.lib
#	-mkdir -p defs
#	../bin/lib2def $< > defs/$@
#
#lib%.a: %.def
#	dlltool --dllname $*.dll  --def defs/$<  --output-lib $@ -k



all-SDK: $(SDKLIBS)

install: all
	install -d $(INSTALLDIR)
	install *.a $(INSTALLDIR)/

distclean clean:
	rm -f *.a defs/*.def

distuninstall:
	for file in $(OURLIBS) $(CYGLIBS) $(SDKLIBS) ;do \
	  rm -f $(INSTALLDIR)/$$file; \
	done
	-rmdir -p $(INSTALLDIR)

uninstall:
	rm -f $(INSTALLDIR)/libcrtdll.a

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: problem building a dll that uses other dll's
       [not found] <199708251740.NAA14070@nut.brown.edu>
@ 1997-08-25 23:11 ` Mikey
       [not found] ` <199708251852.OAA02984@nut.brown.edu>
  1 sibling, 0 replies; 3+ messages in thread
From: Mikey @ 1997-08-25 23:11 UTC (permalink / raw)
  To: dgold, gnu-win32

The dll is not the stub library, the stub library
for foo.dll is libfoo.a

to use ld.exe directly, you would need to do

ld --subsystem [ windows/console ] --dll -e _dll_entry@12 -o prog.exe prog.o -L/search/dir -lfoo

the -l automatically adds the lib prefix, and the .a suffix. to the stub library name

-L is used to add a search path for ld.

The order of files on the link line IS important, since ld is
a one pass linker, references must be resolved by
object files farther allong in the link line.

BTW all of this stuff is in the ld man page, and also
in gcc.info, you might try reading them.


On Mon, 25 Aug 1997 13:42:04 -500, you wrote:

>> You must tell ld (or link.exe) which libraries to
>> link with.
>
>hmm.. what option are you using to do this?  i tried "-l foo.dll" but it 
>doesn't seem to work:
>
>gnuwin32/H-i386-cygwin32/i386-cygwin32/bin/ld.exe: cannot open
>-lhttpdlw.dll: No such file or directory
>
>maybe i just need a different syntax?  but i think it is expecting a .a 
>library.  do you know how to do this?
>
>> easeist way is to let gcc do it.
>> 
>> to link do
>> 
>> gcc -Wl,--dll,-e,_dll_entry@12 -o prog.exe prog.o
>> 
>> the libraries will automatically be linked in.
>
>i tried this, but without specifying the libraries (since i couldn't 
>figure out the syntax for that), and it did the same thing as before - 
>"undefined reference ...".
>
>thanks!
>
>> >I am trying to build a DLL which has function calls which must be
>> >resolved into existing win32 DLL's.
>> >
>> >I am using b18 on winNT 4.0.  i have MSVC 5.0 available.
>> >
>> >Following the instructions for building a relocatable dll, i get an
>> >output but each of the three ld steps reports all the undefined
>> >references for the functions which are in the existing win32 dll's.  i had
>> >to add the --noinhibit-exec option to ld so that it wouldn't delete the
>> >output dll due to the errors.  if i try to use the result dll, it says it 
>> >is an invalid image...
>
>---------------------------------------------------------
>Dan Goldwater          dgold@brown.edu
> http://fatmac.ee.cornell.edu/~goldwada
>---------------------------------------------------------
>
>
>

(jeffdbREMOVETHIS@netzone.com)
delete REMOVETHIS from the above to reply
         Mikey
-
For help on using this list (especially unsubscribing), send a message to
"gnu-win32-request@cygnus.com" with one line of text: "help".

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~1997-08-25 23:11 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-08-22 12:21 problem building a dll that uses other dll's Dan Goldwater
     [not found] <199708251740.NAA14070@nut.brown.edu>
1997-08-25 23:11 ` Mikey
     [not found] ` <199708251852.OAA02984@nut.brown.edu>
1997-08-25 23:11   ` Mikey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).