public inbox for frysk-cvs@sourceware.org
help / color / mirror / Atom feed
From: cagney@sourceware.org
To: frysk-cvs@sourceware.org
Subject: [SCM]  master: Push ProcessIdentifier into live ByteBuffers.
Date: Thu, 07 Feb 2008 17:11:00 -0000	[thread overview]
Message-ID: <20080207171145.2303.qmail@sourceware.org> (raw)

The branch, master has been updated
       via  104895f525b12cf31508c4a2ec3f9f24589a25e9 (commit)
      from  9c26f2e7af2906f4fa80bc346f0d91e3570c9599 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit 104895f525b12cf31508c4a2ec3f9f24589a25e9
Author: Andrew Cagney <cagney@redhat.com>
Date:   Thu Feb 7 12:10:08 2008 -0500

    Push ProcessIdentifier into live ByteBuffers.
    
    frysk-core/frysk/proc/live/ChangeLog
    2008-02-07  Andrew Cagney  <cagney@redhat.com>
    
    	* AddressSpaceByteBuffer.java: Replace "int pid" with
    	ProcessIdentifier.
    	* IsaFactory.java: Ditto.
    	* RegisterSetByteBuffer.java: Ditto.
    	* LogicalMemoryBuffer.java: Ditto.
    	* PtraceRegisterBanksFactory.java: Ditto.
    	* LinuxPtraceTask.java (tid): New.
    	* TestByteBuffer.java: Update.

-----------------------------------------------------------------------

Summary of changes:
 .../frysk/proc/live/AddressSpaceByteBuffer.java    |   21 ++--
 frysk-core/frysk/proc/live/ChangeLog               |    9 ++
 frysk-core/frysk/proc/live/IsaFactory.java         |  102 +++++++----------
 frysk-core/frysk/proc/live/LinuxPtraceTask.java    |   37 ++++---
 .../frysk/proc/live/LogicalMemoryBuffer.java       |   40 ++++---
 .../proc/live/PtraceRegisterBanksFactory.java      |   11 +-
 .../frysk/proc/live/RegisterSetByteBuffer.java     |   19 ++--
 frysk-core/frysk/proc/live/TestByteBuffer.java     |  118 +++++++++-----------
 8 files changed, 174 insertions(+), 183 deletions(-)

First 500 lines of diff:
diff --git a/frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java b/frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java
index fbf3393..a2d2f25 100644
--- a/frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java
+++ b/frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java
@@ -1,6 +1,6 @@
 // This file is part of the program FRYSK.
 // 
-// Copyright 2007, Red Hat Inc.
+// Copyright 2007, 2008, Red Hat Inc.
 // 
 // FRYSK is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by
@@ -41,23 +41,22 @@ package frysk.proc.live;
 
 import inua.eio.ByteBuffer;
 import frysk.sys.Errno;
+import frysk.sys.ProcessIdentifier;
 import frysk.sys.Ptrace.AddressSpace;
 import frysk.sys.proc.Mem;
 import frysk.event.Request;
 import frysk.proc.Manager;
 
-public class AddressSpaceByteBuffer
-    extends ByteBuffer
-{
+public class AddressSpaceByteBuffer extends ByteBuffer {
     protected final AddressSpace addressSpace;
-    protected final int pid;
+    protected final ProcessIdentifier pid;
 
     // Direct files access if possible, or null otherwise.
     final Mem mem;
 
-    protected AddressSpaceByteBuffer (int pid, AddressSpace addressSpace,
-				    long lowerExtreem, long upperExtreem)
-    {
+    protected AddressSpaceByteBuffer (ProcessIdentifier pid,
+				      AddressSpace addressSpace,
+				      long lowerExtreem, long upperExtreem) {
 	super (lowerExtreem, upperExtreem);
 	this.pid = pid;
 	this.addressSpace = addressSpace;
@@ -72,9 +71,9 @@ public class AddressSpaceByteBuffer
 	else
 	  mem = null;
     }
-    public AddressSpaceByteBuffer (int pid, AddressSpace addressSpace)
-    {
-	this (pid, addressSpace, 0, addressSpace.length ());
+    public AddressSpaceByteBuffer(ProcessIdentifier pid,
+				  AddressSpace addressSpace) {
+	this(pid, addressSpace, 0, addressSpace.length());
     }
 
 
diff --git a/frysk-core/frysk/proc/live/ChangeLog b/frysk-core/frysk/proc/live/ChangeLog
index ef7a60b..eb91260 100644
--- a/frysk-core/frysk/proc/live/ChangeLog
+++ b/frysk-core/frysk/proc/live/ChangeLog
@@ -1,5 +1,14 @@
 2008-02-07  Andrew Cagney  <cagney@redhat.com>
 
+	* AddressSpaceByteBuffer.java: Replace "int pid" with
+	ProcessIdentifier.
+	* IsaFactory.java: Ditto.
+	* RegisterSetByteBuffer.java: Ditto.
+	* LogicalMemoryBuffer.java: Ditto.
+	* PtraceRegisterBanksFactory.java: Ditto.
+	* LinuxPtraceTask.java (tid): New.
+	* TestByteBuffer.java: Update.
+
 	* TestByteBuffer.java: Use ForkFactory.
 
 2008-02-06  Andrew Cagney  <cagney@redhat.com>
diff --git a/frysk-core/frysk/proc/live/IsaFactory.java b/frysk-core/frysk/proc/live/IsaFactory.java
index 2c262ab..298a116 100644
--- a/frysk-core/frysk/proc/live/IsaFactory.java
+++ b/frysk-core/frysk/proc/live/IsaFactory.java
@@ -1,6 +1,6 @@
 // This file is part of the program FRYSK.
 //
-// Copyright 2006, 2007, Red Hat Inc.
+// Copyright 2006, 2007, 2008, Red Hat Inc.
 //
 // FRYSK is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by
@@ -49,7 +49,7 @@ import lib.dwfl.ElfEHeader;
 import lib.dwfl.ElfEMachine;
 import lib.dwfl.ElfException;
 import lib.dwfl.ElfFileException;
-import frysk.proc.Task;
+import frysk.sys.ProcessIdentifier;
 
 public class IsaFactory
 {
@@ -77,50 +77,48 @@ public class IsaFactory
     return factory;
   }
 
-  /**
-   * Obtain ISA of task via pid.
-   *
-   * XXX: Instead of reading /proc/PID/exe, and relying on its
-   * presence, this code should do something like read /proc/PID/auxv
-   * and the processor memory to directly figure out what the ISA is.
-   * There are already race coditions, such as during termination,
-   * where /proc/PID/exe is no longer valid but the processes memory
-   * is still readable.
-   */
-  private Isa getIsa(int pid, Task task) 
-  {
-    logger.log (Level.FINE, "{0} getIsa\n", this);
-    
-    // FIXME: This should use task.proc.getExe().  Only that causes
-    // wierd failures; take a rain-check :-(
-    String exe;
-    try {
-	exe = new File("/proc/" + pid + "/exe").getCanonicalPath();
-    } catch (java.io.IOException e) {
-	throw new RuntimeException(MESSAGE, e);
-    }
-    Elf elfFile;
-    try {
-	elfFile = new Elf(exe, ElfCommand.ELF_C_READ);
-    } catch (ElfFileException e) {
-	throw new RuntimeException (MESSAGE, e);
-    }
-    catch (ElfException e) {
-	throw new RuntimeException (MESSAGE, e);
-    }
-
-    try {
-	ElfEHeader header = elfFile.getEHeader();
-	Isa isa = (Isa)isaHash.get(Integer.valueOf(header.machine));
-	if (isa == null)
-	    // A "can't happen".
-	    throw new RuntimeException ("Unknown machine type " + header.machine);
-	return isa;
-    }
-    finally {
-	elfFile.close();
+    /**
+     * Obtain ISA of task via pid.
+     *
+     * XXX: Instead of reading /proc/PID/exe, and relying on its
+     * presence, this code should do something like read
+     * /proc/PID/auxv and the processor memory to directly figure out
+     * what the ISA is.  There are already race coditions, such as
+     * during termination, where /proc/PID/exe is no longer valid but
+     * the processes memory is still readable.
+     */
+    Isa getIsa(ProcessIdentifier pid) {
+	logger.log (Level.FINE, "{0} getIsa\n", this);
+	
+	// FIXME: This should use task.proc.getExe().  Only that
+	// causes wierd failures; take a rain-check :-(
+	String exe;
+	try {
+	    exe = new File("/proc/" + pid + "/exe").getCanonicalPath();
+	} catch (java.io.IOException e) {
+	    throw new RuntimeException(MESSAGE, e);
+	}
+	Elf elfFile;
+	try {
+	    elfFile = new Elf(exe, ElfCommand.ELF_C_READ);
+	} catch (ElfFileException e) {
+	    throw new RuntimeException (MESSAGE, e);
+	}
+	catch (ElfException e) {
+	    throw new RuntimeException (MESSAGE, e);
+	}
+	
+	try {
+	    ElfEHeader header = elfFile.getEHeader();
+	    Isa isa = (Isa)isaHash.get(Integer.valueOf(header.machine));
+	    if (isa == null)
+		// A "can't happen".
+		throw new RuntimeException ("Unknown machine type " + header.machine);
+	    return isa;
+	} finally {
+	    elfFile.close();
+	}
     }
-  }
 
   /**
    * Obtain ISA via ElfMachine Type.
@@ -145,18 +143,4 @@ public class IsaFactory
       }
       return isa;
   }
-
-  public Isa getIsa(int pid) {
-	try {
-	    return getIsa(pid, null);
-	} catch (Exception e) {
-	    return null;
-	}
-    }
-  
-  public Isa getIsa(Task task)
-  {
-    return getIsa(task.getTid(), task);
-  }
-  
 }
diff --git a/frysk-core/frysk/proc/live/LinuxPtraceTask.java b/frysk-core/frysk/proc/live/LinuxPtraceTask.java
index 494aede..3753819 100644
--- a/frysk-core/frysk/proc/live/LinuxPtraceTask.java
+++ b/frysk-core/frysk/proc/live/LinuxPtraceTask.java
@@ -60,6 +60,7 @@ import inua.eio.ByteBuffer;
 import inua.eio.ByteOrder;
 import frysk.sys.Errno;
 import frysk.sys.ProcessIdentifier;
+import frysk.sys.ProcessIdentifierFactory;
 import frysk.sys.Ptrace;
 import frysk.sys.Ptrace.AddressSpace;
 import frysk.sys.Signal;
@@ -74,11 +75,14 @@ import frysk.isa.banks.RegisterBanks;
  */
 
 public class LinuxPtraceTask extends LiveTask {
+    private final ProcessIdentifier tid;
+
     /**
      * Create a new unattached Task.
      */
     public LinuxPtraceTask(Proc proc, TaskId id) {
 	super(proc, id);
+	tid = ProcessIdentifierFactory.createFIXME(id.hashCode());
 	newState = LinuxPtraceTaskState.detachedState();
     }
     /**
@@ -87,6 +91,7 @@ public class LinuxPtraceTask extends LiveTask {
     public LinuxPtraceTask(Task task, ProcessIdentifier clone) {
 	// XXX: shouldn't need to grub around in the old task's state.
 	super(task, new TaskId(clone.intValue()));
+	tid = clone;
 	newState = LinuxPtraceTaskState.clonedState(((LinuxPtraceTask)task).getState ());
     }
     /**
@@ -95,6 +100,7 @@ public class LinuxPtraceTask extends LiveTask {
     public LinuxPtraceTask(LinuxPtraceProc proc,
 			   TaskObserver.Attached attached) {
 	super(proc, attached);
+	tid = ProcessIdentifierFactory.createFIXME(proc.getPid());
 	newState = LinuxPtraceTaskState.mainState();
 	if (attached != null) {
 	    TaskObservation ob = new TaskObservation(this, attachedObservers,
@@ -113,7 +119,7 @@ public class LinuxPtraceTask extends LiveTask {
     ByteBuffer getRawMemory() {
 	logger.log(Level.FINE, "Begin fillMemory\n", this);
 	ByteOrder byteOrder = getISA().order();
-	ByteBuffer memory = new AddressSpaceByteBuffer(getTid(),
+	ByteBuffer memory = new AddressSpaceByteBuffer(tid,
 						       AddressSpace.DATA);
 	memory.order(byteOrder);
 	logger.log(Level.FINE, "End fillMemory\n", this); 
@@ -126,7 +132,6 @@ public class LinuxPtraceTask extends LiveTask {
     public ByteBuffer getMemory() {
 	if (memory == null) {
 	    logger.log(Level.FINE, "{0} exiting get memory\n", this);
-	    int tid = getTid();
 	    ByteOrder byteOrder = getISA().order();
 	    BreakpointAddresses breakpoints = ((LinuxPtraceProc)getProc()).breakpoints;
 	    memory = new LogicalMemoryBuffer(tid, AddressSpace.DATA,
@@ -139,7 +144,7 @@ public class LinuxPtraceTask extends LiveTask {
 
     protected RegisterBanks getRegisterBanks() {
 	if (registerBanks == null)
-	    registerBanks = PtraceRegisterBanksFactory.create(getISA(), getTid());
+	    registerBanks = PtraceRegisterBanksFactory.create(getISA(), tid);
 	return registerBanks;
     }
     private RegisterBanks registerBanks;
@@ -167,7 +172,7 @@ public class LinuxPtraceTask extends LiveTask {
     public Isa getIsaFIXME() {
 	logger.log(Level.FINE, "{0} sendrecIsa\n", this);
 	IsaFactory factory = IsaFactory.getSingleton();
-	return factory.getIsa(getTid());
+	return factory.getIsa(tid);
     }
 
     /**
@@ -255,7 +260,7 @@ public class LinuxPtraceTask extends LiveTask {
 	sigSendXXX = sig;
         incrementMod();
 	try {
-	    Ptrace.cont(getTid(), sig);
+	    Ptrace.cont(tid, sig);
 	} catch (Errno.Esrch e) {
 	    postDisappearedEvent(e);
 	}
@@ -265,7 +270,7 @@ public class LinuxPtraceTask extends LiveTask {
 	sigSendXXX = sig;
         incrementMod();
 	try {
-	    Ptrace.sysCall(getTid(), sig);
+	    Ptrace.sysCall(tid, sig);
 	} catch (Errno.Esrch e) {
 	    postDisappearedEvent(e);
 	}
@@ -276,7 +281,7 @@ public class LinuxPtraceTask extends LiveTask {
         incrementMod();
 	syscallSigretXXX = getIsaFIXME().isAtSyscallSigReturn(this);
 	try {
-	    Ptrace.singleStep(getTid(), sig);
+	    Ptrace.singleStep(tid, sig);
 	} catch (Errno.Esrch e) {
 	    postDisappearedEvent(e);
 	}
@@ -285,7 +290,7 @@ public class LinuxPtraceTask extends LiveTask {
     public void sendStop ()
     {
 	logger.log(Level.FINE, "{0} sendStop\n", this);
-	Signal.STOP.tkill(getTid());
+	Signal.STOP.tkill(tid);
     }
 
 
@@ -294,7 +299,7 @@ public class LinuxPtraceTask extends LiveTask {
 	logger.log(Level.FINE, "{0} sendAttach\n", this);
 	try
 	    {
-		Ptrace.attach(getTid());
+		Ptrace.attach(tid);
 
 		/*
 		 * XXX: Linux kernel has a 'feature' that if a process is already
@@ -329,10 +334,10 @@ public class LinuxPtraceTask extends LiveTask {
 	try {
 	    if (sig == Signal.STOP) {
 		logger.log(Level.FINE, "{0} sendDetach/signal STOP\n", this);
-		Signal.STOP.tkill(getTid());
-		Ptrace.detach(getTid(), Signal.NONE);
+		Signal.STOP.tkill(tid);
+		Ptrace.detach(tid, Signal.NONE);
 	    } else {
-		Ptrace.detach(getTid(), sig);
+		Ptrace.detach(tid, sig);
 	    }
 	} catch (Exception e) {
 	    // Ignore problems trying to detach, most of the time the
@@ -349,20 +354,20 @@ public class LinuxPtraceTask extends LiveTask {
 	| Ptrace.optionTraceExec();
     void initializeAttachedState() {
 	logger.log(Level.FINE, "{0} initializeAttachedState\n", this);
-	Ptrace.setOptions(getTid(), ptraceOptions);
+	Ptrace.setOptions(tid, ptraceOptions);
 	// FIXME: This should use task.proc.getExe().  Only that
 	// causes wierd failures; take a rain-check :-(
-	currentISA = ElfMap.getISA(new File("/proc/" + getTid() + "/exe"));
+	currentISA = ElfMap.getISA(new File("/proc/" + tid + "/exe"));
     }
     void startTracingSyscalls() {
 	logger.log(Level.FINE, "{0} startTracingSyscalls\n", this);
 	ptraceOptions |= Ptrace.optionTraceSysgood();
-	Ptrace.setOptions(getTid(), ptraceOptions);
+	Ptrace.setOptions(tid, ptraceOptions);
     }
     void stopTracingSyscalls() {
 	logger.log(Level.FINE, "{0} stopTracingSyscalls\n", this);
 	ptraceOptions &= ~ (Ptrace.optionTraceSysgood());
-	Ptrace.setOptions(getTid(), ptraceOptions);
+	Ptrace.setOptions(tid, ptraceOptions);
     }
 
 
diff --git a/frysk-core/frysk/proc/live/LogicalMemoryBuffer.java b/frysk-core/frysk/proc/live/LogicalMemoryBuffer.java
index 96a7a87..11038ce 100644
--- a/frysk-core/frysk/proc/live/LogicalMemoryBuffer.java
+++ b/frysk-core/frysk/proc/live/LogicalMemoryBuffer.java
@@ -1,6 +1,6 @@
 // This file is part of the program FRYSK.
 //
-// Copyright 2007 Red Hat Inc.
+// Copyright 2007, 2008 Red Hat Inc.
 //
 // FRYSK is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by
@@ -39,6 +39,7 @@
 
 package frysk.proc.live;
 
+import frysk.sys.ProcessIdentifier;
 import java.util.Iterator;
 import inua.eio.ByteBuffer;
 import frysk.sys.Ptrace.AddressSpace;
@@ -55,24 +56,27 @@ class LogicalMemoryBuffer extends AddressSpaceByteBuffer
   // The breakpoints associated with the process address space.
   private final BreakpointAddresses breakpoints;
 
-  // Private constructor used by subBuffer()
-  private LogicalMemoryBuffer(int tid, AddressSpace addressSpace,
-			      BreakpointAddresses breakpoints,
-			      long lower, long upper)
-  {
-    super(tid, addressSpace, lower, upper);
-    this.breakpoints = breakpoints;
-  }
+    /**
+     * Private constructor used by subBuffer()
+     */
+    private LogicalMemoryBuffer(ProcessIdentifier tid,
+				AddressSpace addressSpace,
+				BreakpointAddresses breakpoints,
+				long lower, long upper) {
+	super(tid, addressSpace, lower, upper);
+	this.breakpoints = breakpoints;
+    }
   
-  // Package local contructor used by LinuxTask to create a logical
-  // memory space for a task when requested.
-  LogicalMemoryBuffer(int tid,
-		      AddressSpace addressSpace,
-		      BreakpointAddresses breakpoints)
-  {
-    super(tid, addressSpace);
-    this.breakpoints = breakpoints;
-  }
+    /**
+     * Package local contructor used by LinuxTask to create a logical
+     * memory space for a task when requested.
+     */
+    LogicalMemoryBuffer(ProcessIdentifier tid,
+			AddressSpace addressSpace,
+			BreakpointAddresses breakpoints) {
+	super(tid, addressSpace);
+	this.breakpoints = breakpoints;
+    }
   
   protected int peek(long caret)
   {
diff --git a/frysk-core/frysk/proc/live/PtraceRegisterBanksFactory.java b/frysk-core/frysk/proc/live/PtraceRegisterBanksFactory.java
index 74ee135..e4fc8ac 100644
--- a/frysk-core/frysk/proc/live/PtraceRegisterBanksFactory.java
+++ b/frysk-core/frysk/proc/live/PtraceRegisterBanksFactory.java
@@ -1,6 +1,6 @@
 // This file is part of the program FRYSK.
 //
-// Copyright 2006, 2007, Red Hat Inc.
+// Copyright 2006, 2007, 2008, Red Hat Inc.
 // Copyright 2006, IBM Corp.
 //
 // FRYSK is free software; you can redistribute it and/or modify it
@@ -43,6 +43,7 @@ package frysk.proc.live;
 import inua.eio.ByteBuffer;
 import inua.eio.ByteOrder;
 import frysk.isa.ISA;
+import frysk.sys.ProcessIdentifier;
 import frysk.sys.Ptrace.RegisterSet;
 import frysk.sys.Ptrace.AddressSpace;
 import frysk.isa.banks.RegisterBanks;
@@ -57,7 +58,7 @@ import frysk.Config;
 
 class PtraceRegisterBanksFactory {
 
-    private static ByteBuffer[] x8664Banks(int pid) {
+    private static ByteBuffer[] x8664Banks(ProcessIdentifier pid) {
 	ByteBuffer[] bankBuffers = new ByteBuffer[] {
 	    new RegisterSetByteBuffer(pid, RegisterSet.REGS),
 	    new RegisterSetByteBuffer(pid, RegisterSet.FPREGS),
@@ -69,7 +70,7 @@ class PtraceRegisterBanksFactory {
 	return bankBuffers;
     }
 
-    private static ByteBuffer[] ia32Banks(int pid) {
+    private static ByteBuffer[] ia32Banks(ProcessIdentifier pid) {
 	ByteBuffer[] bankBuffers = new ByteBuffer[] {
 	    new RegisterSetByteBuffer(pid, RegisterSet.REGS),
 	    new RegisterSetByteBuffer(pid, RegisterSet.FPREGS),
@@ -82,7 +83,7 @@ class PtraceRegisterBanksFactory {
 	return bankBuffers;
     }
 
-    private static ByteBuffer[] ppcBanksBE(int pid) {
+    private static ByteBuffer[] ppcBanksBE(ProcessIdentifier pid) {
 	ByteBuffer[] bankBuffers = new ByteBuffer[] {
             new AddressSpaceByteBuffer(pid, AddressSpace.USR)
         };
@@ -93,7 +94,7 @@ class PtraceRegisterBanksFactory {
 	return bankBuffers;
     }
 
-    static RegisterBanks create(ISA isa, int pid) {
+    static RegisterBanks create(ISA isa, ProcessIdentifier pid) {
 	if (isa == ISA.X8664) {
 	    return new RegisterBanks(X86BankRegisters.X8664,
 				     x8664Banks(pid));
diff --git a/frysk-core/frysk/proc/live/RegisterSetByteBuffer.java b/frysk-core/frysk/proc/live/RegisterSetByteBuffer.java
index f0cd6fb..8dd857f 100644
--- a/frysk-core/frysk/proc/live/RegisterSetByteBuffer.java
+++ b/frysk-core/frysk/proc/live/RegisterSetByteBuffer.java
@@ -1,6 +1,6 @@
 // This file is part of the program FRYSK.
 //
-// Copyright 2006, 2007, Red Hat Inc.
+// Copyright 2006, 2007, 2008, Red Hat Inc.
 //
 // FRYSK is free software; you can redistribute it and/or modify it


hooks/post-receive
--
frysk system monitor/debugger


                 reply	other threads:[~2008-02-07 17:11 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080207171145.2303.qmail@sourceware.org \
    --to=cagney@sourceware.org \
    --cc=frysk-cvs@sourceware.org \
    --cc=frysk@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).