--- org/qmail-1.03/qmail-pop3d.c	Mon Jun 15 12:53:16 1998
+++ qmail-1.03/qmail-pop3d.c	Tue Jul 28 19:03:51 1998
@@ -17,6 +17,19 @@
 #include "timeoutread.h"
 #include "timeoutwrite.h"
 
+/*
+ * Define to include a "Status: " header in the mail that reflects whether
+ * the mail has been read.
+ */
+
+#define USE_STATUS_HEADER
+
+/*
+ * Define to include a "X-UIDL: " header to help some clients.
+ */
+
+#define USE_XUIDL_HEADER
+
 void die() { _exit(0); }
 
 int saferead(fd,buf,len) int fd; char *buf; int len;
@@ -72,6 +85,7 @@
 void err_toobig() { err("not that many messages"); }
 void err_nosuch() { err("unable to open that message"); }
 void err_nounlink() { err("unable to unlink all deleted messages"); }
+void err_rename() { err("unable to move message from new/ to cur/"); }
 
 void okay() { puts("+OK \r\n"); flush(); }
 
@@ -84,20 +98,53 @@
 char strnum[FMT_ULONG];
 stralloc line = {0};
 
-void blast(ssfrom,limit)
+stralloc filenames = {0};
+prioq pq = {0};
+
+struct message {
+  int flagdeleted;
+  int flagread;
+  unsigned long size;
+  char *fn;
+} *m;
+int numm;
+
+void blast(ssfrom,limit,i)
 substdio *ssfrom;
 unsigned long limit;
+int i;
 {
   int match;
   int inheaders = 1;
+  int extradone = 0;
  
   for (;;) {
     if (getln(ssfrom,&line,&match,'\n') != 0) die();
     if (!match && !line.len) break;
     if (match) --line.len; /* no way to pass this info over POP */
     if (limit) if (!inheaders) if (!--limit) break;
-    if (!line.len)
+    if (!line.len || !str_diffn(line.s, "Content-Type: ", 14) || !str_diffn(line.s, "-----", 5) )
+    {
+      /* add our status notification here... */
+#if defined(USE_STATUS_HEADER) || defined(USE_XUIDL_HEADER)
+      if (!extradone && (inheaders  || !str_diffn(line.s, "Content-Type: ", 14) || !str_diffn(line.s, "-----", 5) ))
+      {
+#ifdef  USE_STATUS_HEADER
+        if (m[i].flagread)
+          put("Status: RO\r\n",12);
+        else
+          put("Status:  U\r\n",12);
+#endif
+#ifdef USE_XUIDL_HEADER
+        put("X-UIDL: ",8);
+        put(m[i].fn+4,str_chr(m[i].fn+4,':') ? str_chr(m[i].fn+4,':') : str_chr(m[i].fn+4,0));
+        put("\r\n",2);
+#endif
+        extradone = 1;
+      }
+#endif
       inheaders = 0;
+    }
     else
       if (line.s[0] == '.')
         put(".",1);
@@ -109,16 +156,6 @@
   flush();
 }
 
-stralloc filenames = {0};
-prioq pq = {0};
-
-struct message {
-  int flagdeleted;
-  unsigned long size;
-  char *fn;
-} *m;
-int numm;
-
 int last = 0;
 
 void getlist()
@@ -139,10 +176,21 @@
     prioq_delmin(&pq);
     m[i].fn = filenames.s + pe.id;
     m[i].flagdeleted = 0;
+    m[i].flagread = (m[i].fn[0]=='c');
     if (stat(m[i].fn,&st) == -1)
       m[i].size = 0;
     else
-      m[i].size = st.st_size;
+    {
+#ifdef USE_STATUS_HEADER
+     m[i].size = st.st_size + 12; /* account for the 'NEW' status header */
+#else
+     m[i].size = st.st_size ;
+#endif
+#ifdef USE_XUIDL_HEADER
+     /* account for the 'X-UIDL' status header */
+     m[i].size += (str_chr(m[i].fn,':') ? str_chr(m[i].fn,':') : str_chr(m[i].fn,0) ) + 6;
+#endif
+    }
   }
 }
 
@@ -252,7 +300,9 @@
 
 substdio ssmsg; char ssmsgbuf[1024];
 
-void pop3_top(arg) char *arg;
+void do_send(arg,updateread) 
+char *arg;
+int updateread;
 {
   int i;
   unsigned long limit;
@@ -269,17 +319,21 @@
   if (fd == -1) { err_nosuch(); return; }
   okay();
   substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf));
-  blast(&ssmsg,limit);
+  blast(&ssmsg,limit,i);
   close(fd);
+  if (updateread) m[i].flagread=1;
 }
 
+void pop3_top( arg ) char *arg; { do_send(arg,0); }
+void pop3_retr( arg ) char *arg; { do_send(arg,1); }
+
 struct commands pop3commands[] = {
   { "quit", pop3_quit, 0 }
 , { "stat", pop3_stat, 0 }
 , { "list", pop3_list, 0 }
 , { "uidl", pop3_uidl, 0 }
 , { "dele", pop3_dele, 0 }
-, { "retr", pop3_top, 0 }
+, { "retr", pop3_retr, 0 }
 , { "rset", pop3_rset, 0 }
 , { "last", pop3_last, 0 }
 , { "top", pop3_top, 0 }
